#include "QFramework/TQNFTop1jetEstimator.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQCounter.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQStringUtils.h"
#include "QFramework/TQLibrary.h"
#include "QFramework/TQNFChainloader.h"

ClassImp(TQNFTop1jetEstimator)

#define NaN std::numeric_limits<double>::quiet_NaN()

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQNFTop1jetEstimator
//
// This class is intended to calculate a normalization factor for the top background in the (ggF) 
// H->WW->lvlv analysis in the 1jet channel. The implementation tries to reproduce the method used in the ATLAS 
// Higgs->WW publication from 2014/2015 (http://arxiv.org/pdf/1412.2641v1.pdf, page 30f)
// (more is still to be written here)
//
////////////////////////////////////////////////////////////////////////////////////////////////

TQNFTop1jetEstimator::TQNFTop1jetEstimator() : TQNFBase("TOP1JET"),
  fResult(NaN)
{
  // default constructor
}

TQNFTop1jetEstimator::TQNFTop1jetEstimator(TQSampleDataReader* rd) : 
  TQNFBase("TOP1JET"),
  fResult(NaN)
{
  // constructor on reader
  this->setReader(rd);
}

TQNFTop1jetEstimator::TQNFTop1jetEstimator(TQSampleFolder* sf) : 
  TQNFBase("Top1jet"),
  fResult(NaN)
{
  // constructor on reader
  this->setSampleFolder(sf);
}

TQNFTop1jetEstimator::~TQNFTop1jetEstimator(){
  // default destructor
  this->finalize();
}

void TQNFTop1jetEstimator::setRegion1j0b(const TString& region){
  // set the control region (1 jet, 0 b-jets)
  this->fCut10 = region;
}

void TQNFTop1jetEstimator::setRegion1j1b(const TString& region){
  // set the control region (1 jet, 0 b-jets)
  this->fCut11 = region;
}

void TQNFTop1jetEstimator::setRegion2j1b(const TString& region){
  // set the control region (1 jet, 0 b-jets)
  this->fCut21 = region;
}

void TQNFTop1jetEstimator::setRegion2j2b(const TString& region){
  // set the control region (1 jet, 0 b-jets)
  this->fCut22 = region;
}

TString TQNFTop1jetEstimator::getRegion1j0b(){
  // get the control region (1 jet, 0 b-jets)
  return this->fCut10;
}

TString TQNFTop1jetEstimator::getRegion1j1b(){
  // get the control region (1 jet, 1(+) b-jet(s))
  return this->fCut11;
}

TString TQNFTop1jetEstimator::getRegion2j1b(){
  // get the control region (2 jets, 1 b-jet)
  return this->fCut21;
}

TString TQNFTop1jetEstimator::getRegion2j2b(){
  // get the control region (2 jets, 2(+) b-jets)
  return this->fCut22;
}

TString TQNFTop1jetEstimator::getPathMC(){
  // return the (MC)-Path from which the information is retrieved
  return this->fPath;
}

TString TQNFTop1jetEstimator::getPathData(){
  // return the (MC)-Path from which the information is retrieved
  return this->fPathData;
}

void TQNFTop1jetEstimator::setPathMC(const TString& path){
  // set/change the MC path from which the information is retrieved
  this->fPath = path;
}

void TQNFTop1jetEstimator::setPathData(const TString& path){
  // set/change the data path from which the information is retrieved
  this->fPathData = path;
}


bool TQNFTop1jetEstimator::readConfiguration(TQFolder*f){
  // read a configuration from a TQFolder
  // the following tags are read and interpreted:
  // - verbosity: integer, increasing number increases verbosity
  // - cut1j0b: string, name of cut for the 1jet, 0 b-jets region
  // - cut1j1b: string, name of cut for the 1jet, 1 (or more) b-jet(s) region
  // - cut2j1b: string, name of cut for the 2jet, 1 b-jets region
  // - cut2j2b: string, name of cut for the 2jet, 2 (or more) b-jet(s) region
  // - path: the path to be used for the MC sample to be estimated
  // For how the different regions are used, see 
  // all tags are copied to the calculator
  if(!f){
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to configure from NULL folder");
    return false;
  }
  this->importTags(f);
  //@tag:[verbosity] This object tag sets the objects verbosity. Imported from argument in TQNFTop1jetEstimator::readConfiguration unless already present.
  this->getTagInteger("verbosity",this->verbosity);
  TString cutname;
  int n = 0;
  //@tag:[pathMC] This argument tag sets the path to retrieve MC counters from. This tag is obligatory!
  if(!f->getTagString("pathMC",this->fPath)){
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to retrieve MC path");
    return false;
  }
  //@tag:[pathData] This argument tag sets the path to retrieve data counters from. This tag is obligatory!
  if (!f->getTagString("pathData",this->fPathData)) {
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to retrieve data path");
    return false;
  }
  //@tag:[cut1j0b,cut1j1b,cut2j1b,cut2j2b] These argument tags set the cut names for the 1jet, 0b-tag region (cut1j0b, rest analogously). These tags are obligatory!
  if(f->getTagString("cut1j0b",cutname)){
    this->setRegion1j0b(cutname);
    n++;
  } else {
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to retrieve cut name for cut1j0b");
  }
  if(f->getTagString("cut1j1b",cutname)){
    this->setRegion1j1b(cutname);
    n++;
  } else {
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to retrieve cut name for cut1j1b");
  }
  if(f->getTagString("cut2j1b",cutname)){
    this->setRegion2j1b(cutname);
    n++;
  } else {
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to retrieve cut name for cut2j1b");
  }
  if(f->getTagString("cut2j2b",cutname)){
    this->setRegion2j2b(cutname);
    n++;
  } else {
    if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to retrieve cut name for cut2j2b");
  }
  if(n!=4){
    std::cout << "Only found "<<n<<" out of 4 required regions!"<< std::endl;
    messages.activeStream().flush();
    return false;
  }
  
  //read list of background paths to be subtracted from data before the actual calculation is done
  vBkgPaths.clear();
  TQFolderIterator sitr(f->getListOfFolders("samples/?"),true);
  while(sitr.hasNext()){
    TQFolder* sample = sitr.readNext();
    if(!sample) continue;
    //@tag:[name,path] These sub-folder argument tags determine the name and path of background samples which are to be subtracted from data. "name" defaults to the sample name and serves itself as a fallback for the "path" tag.
    TString name = sample->getTagStringDefault("name",sample->getName());
    TString path = sample->getTagStringDefault("path",name);
    vBkgPaths.push_back(path);
  }
  
  return true;
}

double TQNFTop1jetEstimator::getResult(int mode){
  // retrieve the Result
  switch(mode) {
    case 0: 
      return this->fResult;
    case 2:
      return this->fResultExtrapolation;
    case 3:
      return this->fResultEpsilon1Jet;
    case 4:
      return this->fResultGammaMC;
    case 5:
      return this->fResultEpsilon2JetData;
  }
  ERRORclass("Invalid mode '%d', returning NaN.",mode);
  return NaN;
}

void TQNFTop1jetEstimator::printResult(int mode){
  // print the result to the console
  if(TQUtils::isNum(this->getResult(mode))){
    std::cout << this->getResult(mode) << std::endl;
    return;
  }
  std::cout << "<invalid result>" << std::endl;
}

bool TQNFTop1jetEstimator::finalizeSelf(){
  if(this->cnt_mc_10){ delete this->cnt_mc_10; this->cnt_mc_10 = NULL; }
  if(this->cnt_mc_11){ delete this->cnt_mc_11; this->cnt_mc_11 = NULL; }
  if(this->cnt_mc_21){ delete this->cnt_mc_21; this->cnt_mc_21 = NULL; }
  if(this->cnt_mc_22){ delete this->cnt_mc_22; this->cnt_mc_22 = NULL; }
  if(this->cnt_data_11){ delete this->cnt_data_11; this->cnt_data_11 = NULL; }
  if(this->cnt_data_21){ delete this->cnt_data_21; this->cnt_data_21 = NULL; }
  if(this->cnt_data_22){ delete this->cnt_data_22; this->cnt_data_22 = NULL; }
  for (size_t i=0; i< this->vBkgCounters11.size(); ++i) {
    if (this->vBkgCounters11.at(i)) { delete this->vBkgCounters11.at(i); this->vBkgCounters11.at(i) = NULL; }
  }
  this->vBkgCounters11.clear();
  for (size_t i=0; i< this->vBkgCounters21.size(); ++i) {
    if (this->vBkgCounters21.at(i)) { delete this->vBkgCounters21.at(i); this->vBkgCounters21.at(i) = NULL; }
  }
  this->vBkgCounters21.clear();
  for (size_t i=0; i< this->vBkgCounters22.size(); ++i) {
    if (this->vBkgCounters22.at(i)) { delete this->vBkgCounters22.at(i); this->vBkgCounters22.at(i) = NULL; }
  }
  this->vBkgCounters22.clear();
  return true;
}

bool TQNFTop1jetEstimator::initializeSelf(){
  // actually perform the calculation and save the results
  // return true if everything went file, false if an error occured
  if(!this->fReader || !this->fReader->getSampleFolder()){
    messages.sendMessage(TQMessageStream::ERROR,"cannot perform calculation without valid sample folder!");
    return false;
  }
  if(fPath.IsNull()){
    messages.sendMessage(TQMessageStream::ERROR,"cannot perform calculation without valid path!");
    return false;
  }
  TQTaggable tmp;
  //@tag:[readScaleScheme] This object tag determines which scale scheme is used when retrieving values entering the NF calculation (e.g. to include results from previous NF calculation steps). Default: ".top1jet.read"
  tmp.setTagString("scaleScheme",this->getTagStringDefault("readScaleScheme",".top1jet.read"));
  this->cnt_mc_10 = this->fReader->getCounter(fPath,fCut10 ,&tmp);
  this->cnt_mc_11 = this->fReader->getCounter(fPath,fCut11 ,&tmp);
  this->cnt_mc_21 = this->fReader->getCounter(fPath,fCut21 ,&tmp);
  this->cnt_mc_22 = this->fReader->getCounter(fPath,fCut22 ,&tmp);
  this->cnt_data_11 = this->fReader->getCounter(fPathData,fCut11 ,&tmp);
  this->cnt_data_21 = this->fReader->getCounter(fPathData,fCut21 ,&tmp);
  this->cnt_data_22 = this->fReader->getCounter(fPathData,fCut22 ,&tmp);
  if(!(cnt_mc_10 && cnt_mc_11 && cnt_mc_21 && cnt_mc_22 && cnt_data_11 && cnt_data_21 && cnt_data_22)){
    if(cnt_mc_10) {delete cnt_mc_10; cnt_mc_10 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' from path '%s'",fCut10.Data(),fPath.Data());
    if(cnt_mc_11) {delete cnt_mc_11; cnt_mc_11 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' from path '%s'",fCut11.Data(),fPath.Data());
    if(cnt_mc_21) {delete cnt_mc_21; cnt_mc_21 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' region from path '%s'",fCut21.Data(),fPath.Data());
    if(cnt_mc_22) {delete cnt_mc_22; cnt_mc_22 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' region from path '%s'",fCut22.Data(),fPath.Data());
    if(cnt_data_11) {delete cnt_data_11; cnt_data_11 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' from path '%s'",fCut11.Data(),fPathData.Data());
    if(cnt_data_21) {delete cnt_data_21; cnt_data_21 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' from path '%s'",fCut21.Data(),fPathData.Data());
    if(cnt_data_22) {delete cnt_data_22; cnt_data_22 = NULL;}
    else if(verbosity > 0) messages.sendMessage(TQMessageStream::ERROR,"unable to obtain counter '%s' from path '%s'",fCut22.Data(),fPathData.Data());
    return false;
  }
  this->vBkgCounters11.clear();
  this->vBkgCounters21.clear();
  this->vBkgCounters22.clear();
  for (uint i=0; i< this->vBkgPaths.size(); ++i) {
    vBkgCounters11.push_back(this->fReader->getCounter(vBkgPaths.at(i),fCut11 ,&tmp));
    vBkgCounters21.push_back(this->fReader->getCounter(vBkgPaths.at(i),fCut21 ,&tmp));
    vBkgCounters22.push_back(this->fReader->getCounter(vBkgPaths.at(i),fCut22 ,&tmp));
  }
  
  return true;
}

bool TQNFTop1jetEstimator::calculate(){
  if (!this->chainLoader) iterationNumber = -1;
  double mc_10 = this->cnt_mc_10->getCounter() ;//* (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPath+":"+this->fCut10),this->cnt_mc_10->getCounter() ,this->cnt_mc_10->getError() ) ); //this should cancel anyways, so we don't want to blow up the uncertainty even more!
  double mc_11 = this->cnt_mc_11->getCounter() * (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPath+":"+this->fCut11),this->cnt_mc_11->getCounter() ,this->cnt_mc_11->getError() ) );
  double mc_21 = this->cnt_mc_21->getCounter() * (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPath+":"+this->fCut21),this->cnt_mc_21->getCounter() ,this->cnt_mc_21->getError() ) );
  double mc_22 = this->cnt_mc_22->getCounter() * (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPath+":"+this->fCut22),this->cnt_mc_22->getCounter() ,this->cnt_mc_22->getError() ) );
  
  
  double data_11 = this->cnt_data_11->getCounter() * ( iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPathData+":"+this->fCut11),this->cnt_data_11->getCounter() ,this->cnt_data_11->getError() ) );
  double data_21 = this->cnt_data_21->getCounter() * ( iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPathData+":"+this->fCut21),this->cnt_data_21->getCounter() ,this->cnt_data_21->getError() ) );
  double data_22 = this->cnt_data_22->getCounter() * ( iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((this->fPathData+":"+this->fCut22),this->cnt_data_22->getCounter() ,this->cnt_data_22->getError() ) );
  
  
  //subtract other backgrounds
  for (uint i=0; i<vBkgPaths.size(); ++i) {
    data_11 -= vBkgCounters11.at(i) ? vBkgCounters11.at(i)->getCounter() * (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((vBkgPaths.at(i)+":"+fCut11),vBkgCounters11.at(i)->getCounter() ,vBkgCounters11.at(i)->getError() ) ) : 0.;
    data_21 -= vBkgCounters21.at(i) ? vBkgCounters21.at(i)->getCounter() * (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((vBkgPaths.at(i)+":"+fCut21),vBkgCounters21.at(i)->getCounter() ,vBkgCounters21.at(i)->getError() ) ) : 0.;
    data_22 -= vBkgCounters22.at(i) ? vBkgCounters22.at(i)->getCounter() * (iterationNumber < 0 ? 1. : this->chainLoader->getRelVariation((vBkgPaths.at(i)+":"+fCut22),vBkgCounters22.at(i)->getCounter() ,vBkgCounters22.at(i)->getError() ) ) : 0.;
  }
  if (data_21+data_22 == 0.) {
    messages.sendMessage(TQMessageStream::ERROR,"Cannot calculate NF, no data events in counters '%s' and '%s' from path '%s'",fCut21.Data(),fCut22.Data(),fPathData.Data());
    return false;
  }
  if (mc_10 == 0.) {
    messages.sendMessage(TQMessageStream::ERROR,"Cannot calculate NF, no MC events in counter '%s' from path '%s'",fCut10.Data(),fPathData.Data());
    return false;
  }
  if (mc_22 == 0.) {
    messages.sendMessage(TQMessageStream::ERROR,"Cannot calculate NF, no MC events in counter '%s' from path '%s'",fCut22.Data(),fPathData.Data());
    return false;
  }
  
  this->fResultEpsilon2JetData = data_22/(0.5*data_21+data_22);
  this->fResultGammaMC = (mc_11*(0.5*mc_21+mc_22)) / ((mc_10+mc_11)*mc_22); //efficiency needs to include all objects in the denominator!
  
  this->fResultEpsilon1Jet = this->fResultGammaMC * this->fResultEpsilon2JetData;
  this->fResultExtrapolation = ( 1-this->fResultEpsilon1Jet)/this->fResultEpsilon1Jet;
  this->fResult = data_11/mc_10 * this->fResultExtrapolation;
  
  messages.sendMessage(TQMessageStream::VERBOSE,"calculated Top1jetEstimator NF: %g ",this->fResult);
  return true;
}

int TQNFTop1jetEstimator::deployResult(const std::vector<TString>& startAtCutNames, const std::vector<TString>& stopAtCutNames, int doOverwrite, bool applyToStopCut){
  // public interface to deploy calculated NFs.
  int retval = 0;
  //set the "regular" (full=XSecCorr*extrapolation) NF (mode=0):
  retval += this->deployResultInternal(startAtCutNames, stopAtCutNames, doOverwrite, applyToStopCut, 0);
  if (this->hasTag("applyToCut.aux") || this->hasTag("applyToCut.aux.0")) {
    //if there's an additional tag present to deploy extrapolation factor seperatelly, we do so (mode = 2):
    retval += this->deployResultInternal(this->getTagVString("applyToCut.aux"), this->getTagVString("stopAtCut.aux"), this->getTagBoolDefault("overwrite.aux",doOverwrite), this->getTagBoolDefault("applyToStopCut.aux",applyToStopCut), 2); //extrapolation factor
    retval += this->deployResultInternal(this->getTagVString("applyToCut.aux"), this->getTagVString("stopAtCut.aux"), this->getTagBoolDefault("overwrite.aux",doOverwrite), this->getTagBoolDefault("applyToStopCut.aux",applyToStopCut), 3); //estimated b-tag eff. in 1jet region
    retval += this->deployResultInternal(this->getTagVString("applyToCut.aux"), this->getTagVString("stopAtCut.aux"), this->getTagBoolDefault("overwrite.aux",doOverwrite), this->getTagBoolDefault("applyToStopCut.aux",applyToStopCut), 4); //2jet->1jet transfer factor (MC)
    retval += this->deployResultInternal(this->getTagVString("applyToCut.aux"), this->getTagVString("stopAtCut.aux"), this->getTagBoolDefault("overwrite.aux",doOverwrite), this->getTagBoolDefault("applyToStopCut.aux",applyToStopCut), 5); //2jet b-tag eff. from data
  }
  return retval;
}


int TQNFTop1jetEstimator::deployResultInternal(const std::vector<TString>& startAtCutNames, const std::vector<TString>& stopAtCutNames, int doOverwrite, bool applyToStopCut, int mode){

  // set the NF according to the desired scale scheme
  // the NF will be deployed at the given path
  if(!TQUtils::isNum(this->fResult)) return false;
  bool overwrite = (doOverwrite == 1);
  // set the NF according to the desired scale scheme(s)
  //@tag:[writeScaleScheme] This object tag determines the list of scale schemes the results of the NF calculation are written to. Default: ".default"
  //mode==1 is not in use here (keeping the enumeration consistent with top0jet estimator)
  TString postfix = this->getPostfix(mode);
  std::vector<TString> writeScaleSchemes = this->getTagVString(TString::Format("writeScaleScheme%s",postfix.Data() ) );
  //we might run on mode != 0, so we use the default (mode == 0) tag version as a fall back:
  if(writeScaleSchemes.size() < 1){
    if (mode <= 0) {
      writeScaleSchemes = this->getTagVString("writeScaleScheme");  
    } else {
      WARNclass("No output scale scheme defined for auxilary results, please fix your config (needs writeScaleScheme.aux.extrapolation, .epsilon1Jet, .gamma, .epsilon2Jet)! Skipping this variant...");
      return 0;
    }
  }
  if(writeScaleSchemes.size() < 1){
    writeScaleSchemes.push_back(this->getTagStringDefault("writeScaleScheme",".default"));
  }
  
  int retval = 0;
  //@tag:[targetPath] This object tag determines the TQFolder path(s) the result of the NF calculation is written to. Multiple folders can be specified using the TQFolder path arithmetics ("path1+path2")
  TString path = this->getTagStringDefault("targetPath",this->fPath);
  std::vector<TString> targets = this->getTargetCuts(startAtCutNames,stopAtCutNames,applyToStopCut);
  for (size_t c=0; c<targets.size(); ++c) {
      TString cutName = targets.at(c);
    TQSampleFolderIterator itr(this->fReader->getListOfSampleFolders(path),true);
    while(itr.hasNext()){
      TQSampleFolder* sf = itr.readNext();
      if(!sf) continue;
      for(size_t k=0; k<writeScaleSchemes.size(); k++){
        int n = sf->setScaleFactor(writeScaleSchemes[k]+":"+cutName+(overwrite?"":"<<"), this->getResult(mode), 0.);
        this->addNFPath(sf->getPath(),cutName,writeScaleSchemes[k]);
        if(n == 0){
          ERRORclass("unable to set scale factor for cut '%s' on path '%s' with scheme '%s'",cutName.Data(),sf->getPath().Data(),writeScaleSchemes[k].Data());
        }
        retval += n;
      }
    }
    // if the info folder is set and valid, we should keep track of all the processes that have NFs applied
    if(this->infoFolder){
      // get the folder which contains the list of processes for which we have NFs
      //@tag:[nfListPattern] This object tag determines the format how the existence of NFs for the target paths/cuts is written to the info folder (if present). Default: ".cut.%s+"
      TQFolder * sfProcessList = this->infoFolder->getFolder(TString::Format(this->getTagStringDefault("nfListPattern",".cut.%s+").Data(),cutName.Data()));
      // get the sample folder which contains the samples for this process
      TList* sflist = this->fReader->getListOfSampleFolders(path);
      TQSampleFolder * processSampleFolder = ( sflist && sflist->GetEntries() > 0 ) ? (TQSampleFolder*)(sflist->First()) : NULL;
      if(sflist) {delete sflist; sflist = NULL;}
      // retrieve the correct title of the process from this folder
      // if there is no process title set, we will use the process name instead
      TString processTitle = path;
      if (processSampleFolder)
        //@tag:[processTitleKey] This object tag determines the name of the process tag used to retrieve the process title from. Default: "style.default.title".
        processSampleFolder->getTagString(this->getTagStringDefault("processTitleKey","style.default.title"), processTitle);
      // after we have aquired all necessary information, we add a new entry 
      // to the list of processes to which NFs have been applied
      sfProcessList->setTagString(TQFolder::makeValidIdentifier(processTitle),processTitle);
    }
  }
  
  return retval;
}

int TQNFTop1jetEstimator::execute(int itrNumber) {
  this->iterationNumber = itrNumber;
  fSuccess = this->calculate();
  if (fSuccess) return 0;
  return -1;
}

bool TQNFTop1jetEstimator::success () {
  return fSuccess;
}

TString TQNFTop1jetEstimator::getPostfix(int mode) {

  switch (mode) {
    case 0:
      return TString(""); 
    //case 1 doesn't exist in top1jet estimation (see top0jet estimator)
    case 2:
      return TString(".aux.extrapolation"); 
    case 3:
      return TString(".aux.epsilon1Jet"); 
    case 4:
      return TString(".aux.gamma"); 
    case 5:
      return TString(".aux.epsilon2Jet");
  }
  WARN("Requested postfix for unsuported mode %d",mode);
  return TString("");
}  

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