#include "QFramework/TQStringUtils.h"
#include "QFramework/TQSample.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQToken.h"
#include "TFile.h"

#include "definitions.h"

// #define _DEBUG_
#include "QFramework/TQLibrary.h"

#ifdef HAS_XAOD
#define XAOD_STANDALONE 1
#include "TChain.h"
#include "xAODRootAccessInterfaces/TActiveEvent.h"
#include "xAODRootAccess/TEvent.h"
#include "xAODRootAccessInterfaces/TVirtualEvent.h"
#include "xAODRootAccess/MakeTransientTree.h"
bool TQSample::gUseTransientTree(true);
#else
bool TQSample::gUseTransientTree(false);
#endif
bool TQSample::gUseAthenaAccessMode(false);

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQSample:
//
// The TQSample class is a representation of a sample. It is a subclass of a TQSampleFolder and
// can therefore additionally serve as container for objects (e.g. analysis results) associated
// with it. An instance of this class can point to a TTree object which will be used as the
// source of event data. This tree may either be contained in this sample itself, or it may be
// contained in an external ROOT file. Either way, you tell the sample where to find the tree
// by passing an argument to setTreeLocation(...).
//
// As the tree will probably be used by several classes, accessing the tree is managed by the
// sample. To get a pointer to the tree, use getTreeToken(...)
//
////////////////////////////////////////////////////////////////////////////////////////////////

ClassImp(TQSample)


//__________________________________________________________________________________|___________

TList * TQSample::splitTreeLocations(TString treeLocations) {

  /* the list of tree locations to return */
  TList * list = 0;

  while (!treeLocations.IsNull()) {
    /* read one tree location */
    TString location;
    TQStringUtils::readUpTo(treeLocations, location, "<");
    TQStringUtils::readBlanks(treeLocations);

    if (TQStringUtils::removeLeading(treeLocations, "<", 2) != 1) {
      /* create the list */
      if (!list) {
        list = new TList();
        list->SetOwner(true);
      }
      /* add the new item to the list */
      list->Add(new TObjString(TQStringUtils::trim(location).Data()));
    } else {
      /* found a single "<" character: stop */
      if (list)
        delete list;
      return 0;
    }
  }

  /* return the list */
  return list;
}

//__________________________________________________________________________________|___________

TQFolder * TQSample::newInstance(const TString& name) {
  // Returns a new and empty instance of the TQSampleFolder class with name <name>
  // if <name> is a valid name and a null pointer otherwise. Please note: this method
  // does exactly the same as TQSampleFolder::newSampleFolder(...) but may be over-
  // written by sub-classes of TQSampleFolder.

  // create and return new instance of TQFolder with name <name>
  TQSample* newSample = new TQSample(name.IsNull() ? this->GetName() : name.Data());
  newSample->fTreeLocation = this->fTreeLocation;
  newSample->fNormalisation = this->fNormalisation;
  return newSample;
}

//__________________________________________________________________________________|___________

TString TQSample::extractFilename(const TString& treeLocation) {

  // find last occurence of ":" ...
  int pos = treeLocation.Last(':');
  if (pos != kNPOS) {
    // ... return string before it
    return treeLocation(0, pos);
  } else {
    // ... or an empty string in case no ':' has been found
    return TString("");
  }
}


//__________________________________________________________________________________|___________

TString TQSample::extractTreename(const TString& treeLocation) {

  // find last occurence of ":" ...
  int pos = treeLocation.Last(':');
  if (pos != kNPOS) {
    // ... return string after it
    return treeLocation(pos + 1, treeLocation.Length());
  } else {
    // ... or the full string in case no ':' has been found
    return treeLocation;
  }
}


//__________________________________________________________________________________|___________

TQSample::TQSample() : TQSampleFolder() {
  // Default constructor of TQSample class: a new instance of TQSample is created
  // and initialized. It will be emtpy and have no base folder and its name will
  // be set to "unkown"
}


//__________________________________________________________________________________|___________

TQSample::TQSample(const TString& name) : TQSampleFolder(name) {
  // Constructor of TQSample class: a new instance of TQSample is created and
  // initialized. It will be emtpy and have no base folder and its name will
  // be set to the value of the parameter "name_" if it is a valid name and
  // "unknown" otherwise
}

//__________________________________________________________________________________|___________

void TQSample::setNormalisation(double normalisation_) {
  // Set the normalisation factor of this sample. This factor will be used by any
  // analysis to scale its results
   if (this->fProxySample) {
    this->fProxySample->setNormalisation(normalisation_);
    return;
  }
  
  fNormalisation = normalisation_;
}


//__________________________________________________________________________________|___________

double TQSample::getNormalisation() {
  // Get the normalisation factor of this sample (= 1. by default)
  if (this->fProxySample) {
    return this->fProxySample->getNormalisation();
  }
  
  return fNormalisation;
}

//__________________________________________________________________________________|___________

void TQSample::setTree(TFile* f, const TString& treename){
  // set the TTree of this sample from the file and the treename given
  DEBUGclass("checking status of file");
  if(!f || f->IsZombie() || !f->IsOpen()){
    INFO("Encountered possible zombie file in sample '%s'!",this->getPath().Data());
    this->fTree = NULL;
    return;
  }
  DEBUGclass("attempting to retrieve tree");
  TTree* tree = dynamic_cast<TTree*>(fFile->Get(treename.Data()));
  //don't return just yet. In case of xAODs we might have  file without a CollectionTree but we might still need the TEvent for handling some meta data
  /*
  if(!tree){
    this->fTree = NULL;
    return;
  }
  */
  DEBUGclass("function called on file '%s' for tree '%s'",f->GetName(),treename.Data());
  // this function is used to encapsule TTree post-processing
#ifdef HAS_XAOD
// #pragma message "using ASG_RELEASE compilation scheme"
  // if we are inside an ASG release, this tree might require special treatment
  // we check this by looking if any branch type includes the string "xAOD"

  bool isxAOD = false;
  TTree* testTree = tree;
  if (!testTree || testTree->GetEntriesFast()<1) { //we might not have a CollectionTree (or an empty one), so let's try to use the MetaData tree to identify the file as an xAOD.
    testTree = dynamic_cast<TTree*>(fFile->Get("MetaData"));
  }
  if (!testTree) return; //if there's also no MetaData tree, we're done.

  TQIterator itr(testTree->GetListOfBranches());
  while(itr.hasNext()){
    TBranch* obj = (TBranch*)(itr.readNext());
    if(TQStringUtils::find(obj->GetClassName(),"xAOD") != kNPOS){
      isxAOD = true;
      break;
    }
  }
  // if we found anything, we use the xAOD::MakeTransientTree method
  if(isxAOD){
    DEBUGclass("identified tree of sample '%s' as xAOD, making transient",this->getPath().Data());
    DEBUGclass("creating new xAOD::TEvent");
    xAOD::TVirtualEvent* evt = xAOD::TActiveEvent::event();
    if(evt){
      DEBUGclass("re-using existing instance of xAOD::TEvent");
      this->fEvent = dynamic_cast<xAOD::TEvent*>(evt);
      if(!this->fEvent) throw std::runtime_error("active instance of TVirtualEvent is not of type TEvent!");
    } else {
      DEBUGclass("creating new instance of xAOD::TEvent");
      this->fEvent = new xAOD::TEvent(gUseAthenaAccessMode? xAOD::TEvent::kAthenaAccess : xAOD::TEvent::kClassAccess);
      this->fEvent->setActive();
    }
    bool ok = (this->fEvent->readFrom( this->fFile, kTRUE, treename ).isSuccess());
    DEBUGclass("calling xAOD::MakeTransientTree on event %x with treename '%s'",this->fEvent,treename.Data());
    if(ok){
      if(tree && TQSample::gUseTransientTree){ //don't try to create a transTree if there isn't even a CollectionTree
        int oldErrorIgnoreLevel = gErrorIgnoreLevel;
        gErrorIgnoreLevel = 2000;
        this->fTree = xAOD::MakeTransientTree( *this->fEvent, treename );
        gErrorIgnoreLevel = oldErrorIgnoreLevel;
        DEBUGclass("retrieved transient tree %x",this->fTree);
        this->fTreeIsTransient = true;
      } else {
        this->fTree = tree;
        this->fTreeIsTransient = false;
      }
    } else {
      WARNclass("TEvent failed to read from input file!");
      //      delete this->fEvent;
      this->fEvent = 0;
    }
    return;
  }
#else
// #pragma message "using plain ROOT compilation scheme"
#endif
  // if control reaches this point, we are either in plain ROOT or at least
  // have a plain ROOT compatible tree. there's not much to do in that case...
  DEBUGclass("identified tree of sample '%s' as plain ROOT, setting data member",this->getPath().Data());
  this->fTree = tree;
  fTreeIsTransient = false;
}

//__________________________________________________________________________________|___________

void TQSample::clearTree(){
  // clear the tree belonging to this sample
  // is called upon returning all tree tokens
  if(fFile){
    this->retractTreeFromFriends();
    if (fFile->IsOpen()){
      DEBUGclass("closing file");
      fFile->Close();
    }
    DEBUGclass("deleting file pointer");
    delete fFile;
  }
#ifdef HAS_XAOD
  fEvent = NULL;
#endif
  fFile = NULL;
  fTree = NULL;
}

//__________________________________________________________________________________|___________

//define the location to a dummy sample to be used in place of actual samples (not for things like friend finding though, hence, only replace it here)
//intended for debugging on foreign sampleFolders
//#define DUMMYSAMPLE "/home/rgugel/containerTest/samples/wjets_skimming/CAFxAOD_wjetsSkimming_bkg_X_top_ttbar_410503_s.part0_group.phys-higgs.410503.e5475_s2726_r7772_r7676_p3042.11391602.PAOD_2L._0000.root:CollectionTree"

bool TQSample::getTree(){
  // retrieves the tree from the file to store it in the sample
    DEBUGclass("trying to retrieve tree");
    /* get and split the tree locations */
    #ifdef DUMMYSAMPLE
    TList * treeLocations = splitTreeLocations(DUMMYSAMPLE);
    #else
    TList * treeLocations = splitTreeLocations(getTreeLocation());
    #endif
    if (!treeLocations) {
      WARN("Failed to obtain tree location for sample %s",this->GetName());
      return false;
    }

    /* the default file- and treename */
    TString defFilename;
    TString defTreename;

    /* iterate over tree locations */
    int nTreeLocations = treeLocations->GetEntries();
    for (int i = 0; i < nTreeLocations && (fTree || i == 0); i++) {

      /* the tree location */
      TString location = treeLocations->At(i)->GetName();
      /* extract file- and treename */
      TString filename = extractFilename(location);
      TString treename = extractTreename(location);

      /* set default file- and treenames */
      if (filename.IsNull() && !defFilename.IsNull())
        filename = defFilename;
      else if (!filename.IsNull() && defFilename.IsNull())
        defFilename = filename;
      if (treename.IsNull() && !defTreename.IsNull())
        treename = defTreename;
      else if (!treename.IsNull() && defTreename.IsNull())
        defTreename = treename;


      if (!filename.IsNull()) {

        // returns NULL if file pointer is 0 or !file->isOpen()
        TFile* myOpenFile = TQUtils::openFile(filename);

        if (myOpenFile) {
          // therefore, we only get here
          // if myOpenFile is valid and open
          if (i == 0) {
            fFile = myOpenFile;
            DEBUGclass("setting tree");
            this->setTree(fFile, treename);
            DEBUGclass("got tree %x",this->fTree);
            if (!fTree) {
              //FIXME: is this really what we want? We might need the file open even if no tree is present (reading meta data!!)
              /*
              fFile->Close();
              delete fFile;
              fFile = 0;
              */
              INFOclass("Failed to retrieve tree from file %s", filename.Data());
              //return false;
            }
          } else {
            if (fTree) fTree->AddFriend(treename.Data(), myOpenFile);
            else ERRORclass("Cannot add tree from file '%s' as a friend tree as no valid tree could be obtained from the first file '%s'",myOpenFile->GetPath(),fFile->GetPath());
          }
        } else { // not a valid and open file
          ERRORclass("Failed to open file while retrieving tree!");
          return false;
        }
      } else {
        /* look for the tree inside this folder */
        TTree* tree = dynamic_cast<TTree*>(getObject(treename.Data()));
        if (tree){
          /* we found the tree: keep the pointer */
          this->fTree = tree;
          this->fTreeIsTransient = false;
        } else {
          /* we couldn't find the tree */
          fTree = NULL;
          return false;
        }
      }
    }

    delete treeLocations;
    DEBUGclass("successfully completed function");
    return true;
}

//__________________________________________________________________________________|___________

void TQSample::promoteTreeToFriends(){
  // promote the tree pointer to some friends
  //TQSampleFolderIterator itr(this->fFriends);

  //while(itr.hasNext()){

  if (this->fFriends == nullptr) return; // when running in single channel mode we never look for friends

  for (auto myFriendSF : (*this->fFriends)) {
    if (! myFriendSF->InheritsFrom(TQSample::Class()) ) { throw std::runtime_error("Attempt to promote tree to friend which is not of type TQSample. A SampleFolder within a Sample should never happen, check your analysis setup!"); return; }
    TQSample* myFriend = static_cast<TQSample*>(myFriendSF);
  //  TQSample* myFriend = dynamic_cast<TQSample*>(itr.readNext());
    DEBUG("promoting tree from sample '%s' to sample '%s'",this->getPath().Data(),myFriend->getPath().Data());
    if(!myFriend->getFile()){
      myFriend->fTree = this->fTree;
#ifdef HAS_XAOD
      myFriend->fEvent = this->fEvent;
#endif
    }
  }
}

void TQSample::retractTreeFromFriends(){
  // retract a tree (and TEvent) pointer from friends
  //TQSampleFolderIterator itr(this->fFriends);
  //while(itr.hasNext()){
  //  TQSample* myFriend = dynamic_cast<TQSample*>(itr.readNext());
  //  if (!myFriend) throw std::runtime_error("Attempt to promote tree to friend which is not of type TQSample. A SampleFolder within a Sample should never happen, check your analysis setup!");

  if (this->fFriends == nullptr) return; // when running in single channel mode we never look for friends

  for (auto myFriendSF : (*this->fFriends)) {
    if (! myFriendSF->InheritsFrom(TQSample::Class()) ) { throw std::runtime_error("Attempt to retract tree from friend which is not of type TQSample. A SampleFolder within a Sample should never happen, check your analysis setup!"); return; }
    TQSample* myFriend = static_cast<TQSample*>(myFriendSF);
    if (myFriend==this) continue; //don't remove the pointer of this instance (yet)
    DEBUG("retracting tree of sample '%s' from sample '%s'",this->getPath().Data(),myFriend->getPath().Data());
    if(!myFriend->getFile()){
      myFriend->fTree = NULL;
#ifdef HAS_XAOD
      myFriend->fEvent = NULL;
#endif
    }
  }

}

//__________________________________________________________________________________|___________

TQToken * TQSample::getTreeToken() {
  // Request a tree token (TQToken). Return a tree token containing a pointer to
  // the TTree object if the tree is accessible, return a null pointer otherwise.
  // Use returnTreeToken(...) to return the tree token after you don't need the
  // tree anymore. The first request of a tree token triggers reading of the tree
  // (opening the ROOT file, in case it is contained in an external file). After
  // every tree token was returned, the tree is released (closing the ROOT file,
  // in case it is contained in an external file).
  //
  // Your code using the tree might look like this:
  //
  // /* try to get a tree token */
  // treeToken = sample->getTreeToken();
  //
  // if (treeToken) {
  // /* get the pointer to the tree */
  // TTree* tree = (TTree*)treeToken->getContent();
  // /* optional: the sample should know who is using the token */
  // treeToken->setOwner(this);
  //
  // /* <use your tree here> */
  //
  // /* return the tree token */
  // sample->returnTreeToken(treeToken);
  // } else {
  // /* for any reason we didn't get a tree
  // * token, so we cannot use the tree */
  // }
  DEBUGclass("entering function");
  
  if (this->fProxySample) {
    return this->fProxySample->getTreeToken();
  }

  bool createdFile = !(this->fFile); //check if we already had an open file in the beginning or if we have opened it during getTree
  if (!fTree) {
    if(this->getTree()){
      this->promoteTreeToFriends();
    }
  }

  if (fTree) {
    DEBUGclass("creating tree token");
    /* create a new tree token */
    TQToken * treeToken = new TQToken();
    treeToken->setContent(fTree);
    /* create the list of tree tokens */
    if (!fTokens) {
      fTokens = new TList();
      fTokens->SetOwner(true);
    }
    /* keep it in our list */
    fTokens->Add(treeToken);
    /* dispense the token */
    DEBUGclass("returning tree token");
    return treeToken;
  }

  if (createdFile && this->fFile) { //close the input file if we just caused it to be opened and didn't get our desired object
    this->clearTree();
  }
  /* no tree and thus no tree token to dispense */
  return NULL;
}

//__________________________________________________________________________________|___________

TQToken * TQSample::getFileToken() {
  // Request a file token (TQToken). Return a file token containing a pointer to
  // the TFile object if it is accessible, return a null pointer otherwise.
  // Use returnToken(...) to return the token after you don't need the file anymore.
  DEBUGclass("entering function");

  if (this->fProxySample) {
    return this->fProxySample->getFileToken();
  }

  bool createdFile = !(this->fFile); //check if we already had an open file in the beginning or if we have opened it during getTree
  if (!fFile) {
    if(this->getTree()){
      this->promoteTreeToFriends();
    }
  }
  if (fFile) {
    DEBUGclass("returning file");
    TQToken * fileToken = new TQToken();
    fileToken->setContent(fFile);
    if (!fTokens) {
      fTokens = new TList();
      fTokens->SetOwner(true);
    }
    fTokens->Add(fileToken);
    return fileToken;
  }


  if (createdFile && this->fFile) { //close the input file if we just caused it to be opened and didn't get our desired object
    this->clearTree();
  }
  return NULL;
}


//__________________________________________________________________________________|___________

TQToken * TQSample::getEventToken() {
  // Request an event token (TQToken). Return a tree token containing a pointer to
  // the TEvent object if the tree is accessible, return a null pointer otherwise.
  // Use returnToken(...) to return the token after you don't need the
  // TEvent anymore. The first request of a tree token triggers reading of the tree
  // (opening the ROOT file, in case it is contained in an external file). After
  // every tree token was returned, the tree is released (closing the ROOT file,
  // in case it is contained in an external file).
#ifdef HAS_XAOD
  DEBUGclass("entering function");
  
  if (this->fProxySample) {
    return this->fProxySample->getEventToken();
  }
  
  bool createdFile = !(this->fFile); //check if we already had an open file in the beginning or if we have opened it during getTree

  if (!fEvent) {
    if(this->getTree()){
      this->promoteTreeToFriends();
    }
  }

  if (fEvent) {
    DEBUGclass("returning TEvent");
    /* create a new token */
    TQToken * eventToken = new TQToken();
    eventToken->setContent(fEvent);
    /* create the list of event tokens */
    if (!fTokens) {
      fTokens = new TList();
      fTokens->SetOwner(true);
    }
    /* keep it in our list */
    fTokens->Add(eventToken);
    /* dispense the token */
    return eventToken;
  }

  if (createdFile && this->fFile) { //close the input file if we just caused it to be opened and didn't get our desired object
    this->clearTree();
  }
  /* no tree and thus no event token to dispense */
  return NULL;
  #else
  ERRORclass("event token was requested, but TEvent class unavailable in standalone release!");
  return NULL;
  #endif
}

//__________________________________________________________________________________|___________

bool TQSample::returnTreeToken(TQToken * &token_) {
  // Return and delete a tree token that is not needed anymore (for
  // details check documentation of getTreeToken()).
  
  if (this->fProxySample) {
    return this->fProxySample->returnTreeToken(token_);
  }
  
  return this->returnToken(token_);
}

//__________________________________________________________________________________|___________

bool TQSample::returnToken(TQToken * &token_) {
  // Return and delete a tree or event token that is not needed
  // anymore
  
  if (this->fProxySample) {
    return this->fProxySample->returnToken(token_);
  }
  
  if (fTokens && fTokens->FindObject(token_)) {

    /* remove and delete this token
     * and reset the pointer to it */
    fTokens->Remove(token_);
    token_ = 0;

    /* close file if all tokens have been returned */
    if (getNTreeTokens() == 0) {
      DEBUGclass("returning tree token - no tokens left, clearing tree");
      this->clearTree();
    } else {
      DEBUGclass("returning tree token - there are still other active tokens");
    }

    /* successfully returned tree token */
    return true;
  } else {
    /* we don't know this token, so ignore it */
    return false;
  }
}


//__________________________________________________________________________________|___________

bool TQSample::setTreeLocation(TString treeLocation_) {
  // Set the tree location. Setting a new tree location will fail, if there are
  // still unreturned tree tokens. In that case, false is returned, and true other-
  // wise.
  //
  // A tree may either be contained in this sample it self, or it may be contained
  // in an external ROOT file:
  //
  // - if the tree is contained in the sample use
  //
  // setTreeLocation("<name_of_the_tree>");
  //
  // - if the tree is contained in an external ROOT file, use:
  //
  // setTreeLocation("<name_of_the_file>:<name_of_the_tree>");
  //
  // Please note: the name of the tree is NOT the name of the pointer, but it is
  // the name of the object returned by tree->GetName() (or in case of an external
  // file, the name of the key).
  
  if (this->fProxySample) {
    return this->fProxySample->setTreeLocation(treeLocation_);
  }
  
  if (getNTreeTokens() == 0) {
    /* set the new tree location */
    fTreeLocation = treeLocation_;
    /* we successfully set the tree location */
    return true;
  } else {
    /* there are still tree tokens unreturned */
    return false;
  }

}


//__________________________________________________________________________________|___________

int TQSample::getNTreeTokens() {
  // Return the number of unreturned tree tokens
  
  if (this->fProxySample) {
    return this->fProxySample->getNTreeTokens();
  }
  
  if (fTokens)
    return fTokens->GetEntries();
  else
    return 0;
}


//__________________________________________________________________________________|___________

void TQSample::printTreeTokens() {
  // Print a summary of tree tokens
  if (this->fProxySample) {
    this->fProxySample->printTreeTokens();
    return;
  }
  
  TQIterator itr(fTokens);
  while (itr.hasNext()) {
    TQToken * token = dynamic_cast<TQToken*>(itr.readNext());
    if (token) {
      token->print();
    }
  }
}


//__________________________________________________________________________________|___________

bool TQSample::checkTreeAccessibility() {
  // Return true if the TTree is accessible and false otherwise
  
  if (this->fProxySample) {
    return this->fProxySample->checkTreeAccessibility();
  }
  
  bool isAccessible = false;

  /* try to access the tree */
  TQToken * token = getTreeToken();

  if (token) {
    isAccessible = true;
    returnTreeToken(token);
  }

  return isAccessible;
}


//__________________________________________________________________________________|___________

bool TQSample::updateTreeLocation() {
  // Update the internally stored tree location based on xsp or initializer tags
  
  if (this->fProxySample) {
    return this->fProxySample->updateTreeLocation();
  }
  
    TString filepath,treename;
    if( ( this->getTagString(".xsp.filepath",filepath) && this->getTagString(".xsp.treename",treename) ) ||
   ( this->getTagString(".init.filepath",filepath) && this->getTagString(".init.treename",treename) )           ){
      this->fTreeLocation = filepath + ":" + treename;
    }

  return true;
}


//__________________________________________________________________________________|___________

TString TQSample::getTreeLocation() {
  // Return the tree location
  
  if (this->fProxySample) {
    return this->fProxySample->getTreeLocation();
  }
  
  if(this->fTreeLocation.IsNull()){
    this->updateTreeLocation();
  }
  if (TQStringUtils::hasWildcards(fTreeLocation)) {
    throw std::runtime_error(TString::Format("TreeLocation of sample '%s' is not fully resolved but contains wildcards. The tree might not be retrieved correctly!",this->GetName()).Data());
  }
  return fTreeLocation;
}

//__________________________________________________________________________________|___________

const TString& TQSample::getTreeLocationRef() {
  //Returns the treeLocation as a const reference
  //no checks except for empty internal cache are performed.
  
  if (this->fProxySample) {
    return this->fProxySample->getTreeLocationRef();
  }
  
  if (this->fTreeLocation.IsNull()) {
    this->updateTreeLocation();
  }
  return this->fTreeLocation;
}

//__________________________________________________________________________________|___________

TString TQSample::getFilename() {
  // retrieve the filename associated with this sample
  
  if (this->fProxySample) {
    return this->fProxySample->getFilename();
  }
  
  TList * treeLocations = splitTreeLocations(fTreeLocation);
  TString treeLocation;
  if (treeLocations) {
    if (treeLocations->GetEntries() > 0)
      treeLocation = TString(treeLocations->First()->GetName());
    delete treeLocations;
  }

  return extractFilename(treeLocation);
}


//__________________________________________________________________________________|___________

TString TQSample::getTreename() {
  // retrieve the treename associated with this sample
  
  if (this->fProxySample) {
    return this->fProxySample->getTreename();
  }
  
  TList * treeLocations = splitTreeLocations(fTreeLocation);
  TString treeLocation;
  if (treeLocations) {
    if (treeLocations->GetEntries() > 0)
      treeLocation = TString(treeLocations->First()->GetName());
    delete treeLocations;
  }

  return extractTreename(treeLocation);
}


//__________________________________________________________________________________|___________

bool TQSample::addSubSample(TQSample * subSample) {
  // add a subsample to this sample
  // can only be done if this sample is not already a subsample
  if(this->isSubSample()){
    return false;
  }
  if (!subSample) {
    return false;
  }
  if(!this->addFolder(subSample)) {
    return false;
  }
  return true;
}


//__________________________________________________________________________________|___________

TQSample* TQSample::addSelfAsSubSample(const TString& name) {
  // add a copy of yourself as a subsample

  if(name.IsNull()) return NULL;
  TQSample* subSample = new TQSample(name);
  if(!this->addSubSample(subSample)){
    delete subSample;
    return NULL;
  }

  subSample->importTags(this);
  return subSample;
}



//__________________________________________________________________________________|___________

TQSample * TQSample::getSubSample(const TString& path) {
  // get the subsample matching a given path

  TQSampleFolder * sampleFolder = getSampleFolder(path);
  if (sampleFolder && sampleFolder->InheritsFrom(TQSample::Class()))
    return static_cast<TQSample*>(sampleFolder);
  else
    return 0;
}

//__________________________________________________________________________________|___________

bool TQSample::isSubSample(){
  // return true if this sample is the direct child of some other sample
  // false otherwise
  return this->getBaseSample();
}

//__________________________________________________________________________________|___________

TQSample * TQSample::getBaseSample() {
  // retrieve the base sample of this sample
  return dynamic_cast<TQSample*>(this->getBase());
}

//__________________________________________________________________________________|___________

TFile* TQSample::getFile(){
  // retrieve the file pointer of this sample
  
  if (this->fProxySample) {
    return this->fProxySample->getFile();
  }
  
  return this->fFile;
}

//__________________________________________________________________________________|___________

TQSample::~TQSample() {
  // default destructor
  if (fTokens) {
    delete fTokens;
    fTokens = nullptr;
  }
  
}

//__________________________________________________________________________________|___________


bool TQSample::hasSubSamples() {
  // determine if this sample has any sub-samples
  /* try to find a sub sample */
  //for performance reasons we do not use the path parsing version but manualy check for contents of type TQSample
  TCollection * contents = this->GetListOfFolders();
  if (!contents) return false;
  TIterator * itr = contents->MakeIterator();
  if (!itr) return false;

  bool retval = false;

  TObject * obj = nullptr;
  while ( (obj = itr->Next() ) ) {
    if (obj->InheritsFrom(TQSample::Class())) {
      retval = true;
      break;
    }
  }
  delete itr;
  return retval;
}

//__________________________________________________________________________________|___________

bool TQSample::createFriendLinksForSamplesWithTreeLocation(TQSampleFolder* otherSF, std::shared_ptr<TList> otherSFContents) {
  // crawl all samples in otherSF at once, creating friend links between all of them
  // returns true if 'this' sample is amongst the processed TQSample instances
  // and false otherwise.
  if (!otherSF) otherSF = this;
  bool isIncluded = false;
  if (!otherSFContents) otherSFContents = std::shared_ptr<TList>( otherSF->getListOfSampleFolders("*", TQSample::Class()) );
  TQSampleIterator itr(otherSFContents.get());
  std::map<int,std::map<TString,TQSample*>> locationMap; //indices: distToRoot, treeLocation
  while(itr.hasNext()) {
    TQSample* thisSample = itr.readNext();
    if (!thisSample) continue;
    if (thisSample == this) isIncluded = true;
    if (thisSample->hasFriends()) continue; //safe some performance for already connected samples
    TString location = thisSample->getTreeLocation();
    if (location.Length() > 0 || !thisSample->hasSubSamples()) {
      int distToRoot = thisSample->getDistToRoot();
      if (location.Length() == 0) { //all samples without subsamples need to be in one group in order to ensure that the backpropagation to higher level sample(folder)s works!
        location = TString("<noFile>");
      }
      TQSample* existing = locationMap[distToRoot][location];
      if (existing) { //there was already a sample with this tree location at some point, let's befriend with it.
        existing->befriend(thisSample);
      } else { //we have not yet encountered a sample with this tree location
        thisSample->befriend(thisSample);
        locationMap[distToRoot][location] = thisSample;
      }
    }
  }
  return isIncluded;
}

//__________________________________________________________________________________|___________

void TQSample::findFriendsInternal(TQSampleFolder* otherSF, bool forceUpdateSubsamples, std::shared_ptr<TList> otherSFContents){
  // find the friends of this sample folder in some other sample folder

  //create all links between samples in otherSF: (reduced complexity ( N^2 -> N*log(N) ) compared to individual iterations!)
  //note: the actual "filter" which reduces the complexity is the calling "findFriends" method in TQSampleFolder which,
  //unless
  bool isLinked = this->hasFriends() || this->createFriendLinksForSamplesWithTreeLocation(otherSF, otherSFContents);
  bool hasSubSamples = this->hasSubSamples();
  const int thisDistToRoot = this->getDistToRoot();
  if (!isLinked || hasSubSamples) {
    if (!otherSFContents) otherSFContents = std::shared_ptr<TList>( otherSF->getListOfSampleFolders("*", TQSample::Class()) ); //only including TQSamples here as even for subfolders we won't deal with anything but TQSamples (at least) from now on.
    TQSampleIterator itr(otherSFContents.get());
    if (!isLinked) { //this part is only relevant if this sample hasn't been processed yet.
      const TString myTreeLocation = this->getTreeLocation();
      if (myTreeLocation.Length()>0 || !hasSubSamples) { //we don't want to consider super-samples which don't have a tree themselves (this would cause a lot of mis-matching!)

        while(itr.hasNext()){
          TQSample* s = itr.readNext();
          if (!s || s->hasFriends()) continue; //if the other sample already has friends we don't need to bother, it's already done
          if (thisDistToRoot != s->getDistToRoot()) continue; //only create friends if they are at the same depth. Otherwise initialization on folders gets out-of-sync
          const TString treelocation = s->getTreeLocation();
          DEBUGclass("looking at friend candidate '%s'",s->getPath().Data());
          if(TQStringUtils::equal(treelocation,myTreeLocation) ){
            DEBUGclass("found friend '%s'",s->getPath().Data());
            //INFOclass("befriending fundamental samples");
            this->befriend(s);
            break; //we're already done here as friend lists are shared pointers, i.e., if we befriend one sample we automatically befriend all with the same treeLocation
          }
        }
      }
    }
    //now check if all sub-samples are friends and if so, befriend with their sup-folder
    if (hasSubSamples) {
      itr.reset();
      TQSampleIterator subitr(this->getListOfSamples("?"));
      //TQSampleIterator subitr(this->GetListOfFolders());
      while(itr.hasNext()){
        TQSample* other = itr.readNext();
        //we apply the requirements: existence (not a null pointer), the other sample has not already found its set of friends, has sub samples, same number of (sub) samples as this sample.
        if (!other || thisDistToRoot != other->getDistToRoot() || other->hasFriends() || !other->hasSubSamples() || this->getNSamples() != other->getNSamples() ) continue;
        bool befriend = true;
        while(subitr.hasNext() && befriend) {
          TQSample* thisSub = subitr.readNext();
          if (!thisSub) continue;
          TQSample* otherSub = other->getSubSample(thisSub->GetName());
          if (!otherSub) {befriend = false; break;}

          if (forceUpdateSubsamples || (!thisSub->hasFriends()) ) thisSub->findFriends(otherSF, forceUpdateSubsamples);
          if (forceUpdateSubsamples || (!otherSub->hasFriends()) ) otherSub->findFriends(otherSF, forceUpdateSubsamples);

          befriend = befriend && thisSub->isFriend(otherSub);
        }
        subitr.reset();

        //only create friends if they are at the same depth. Otherwise initialization on folders gets out-of-sync
        //doing this check this late is crucial to performance as it reduces the number of getListOfSamples("?") and getListOfSampleFolders("*") calls  which are very expensive!
        //befriend = befriend && (thisDistToRoot == other->getDistToRoot());

        if (befriend) {
          //INFOclass("Befriending super samples ");
          this->befriend(other);
        }
      }
    }
  }

}

//__________________________________________________________________________________|___________

int TQSample::getOwnSize() const {
  return sizeof(*this);
}
 TQSample.cxx:1
 TQSample.cxx:2
 TQSample.cxx:3
 TQSample.cxx:4
 TQSample.cxx:5
 TQSample.cxx:6
 TQSample.cxx:7
 TQSample.cxx:8
 TQSample.cxx:9
 TQSample.cxx:10
 TQSample.cxx:11
 TQSample.cxx:12
 TQSample.cxx:13
 TQSample.cxx:14
 TQSample.cxx:15
 TQSample.cxx:16
 TQSample.cxx:17
 TQSample.cxx:18
 TQSample.cxx:19
 TQSample.cxx:20
 TQSample.cxx:21
 TQSample.cxx:22
 TQSample.cxx:23
 TQSample.cxx:24
 TQSample.cxx:25
 TQSample.cxx:26
 TQSample.cxx:27
 TQSample.cxx:28
 TQSample.cxx:29
 TQSample.cxx:30
 TQSample.cxx:31
 TQSample.cxx:32
 TQSample.cxx:33
 TQSample.cxx:34
 TQSample.cxx:35
 TQSample.cxx:36
 TQSample.cxx:37
 TQSample.cxx:38
 TQSample.cxx:39
 TQSample.cxx:40
 TQSample.cxx:41
 TQSample.cxx:42
 TQSample.cxx:43
 TQSample.cxx:44
 TQSample.cxx:45
 TQSample.cxx:46
 TQSample.cxx:47
 TQSample.cxx:48
 TQSample.cxx:49
 TQSample.cxx:50
 TQSample.cxx:51
 TQSample.cxx:52
 TQSample.cxx:53
 TQSample.cxx:54
 TQSample.cxx:55
 TQSample.cxx:56
 TQSample.cxx:57
 TQSample.cxx:58
 TQSample.cxx:59
 TQSample.cxx:60
 TQSample.cxx:61
 TQSample.cxx:62
 TQSample.cxx:63
 TQSample.cxx:64
 TQSample.cxx:65
 TQSample.cxx:66
 TQSample.cxx:67
 TQSample.cxx:68
 TQSample.cxx:69
 TQSample.cxx:70
 TQSample.cxx:71
 TQSample.cxx:72
 TQSample.cxx:73
 TQSample.cxx:74
 TQSample.cxx:75
 TQSample.cxx:76
 TQSample.cxx:77
 TQSample.cxx:78
 TQSample.cxx:79
 TQSample.cxx:80
 TQSample.cxx:81
 TQSample.cxx:82
 TQSample.cxx:83
 TQSample.cxx:84
 TQSample.cxx:85
 TQSample.cxx:86
 TQSample.cxx:87
 TQSample.cxx:88
 TQSample.cxx:89
 TQSample.cxx:90
 TQSample.cxx:91
 TQSample.cxx:92
 TQSample.cxx:93
 TQSample.cxx:94
 TQSample.cxx:95
 TQSample.cxx:96
 TQSample.cxx:97
 TQSample.cxx:98
 TQSample.cxx:99
 TQSample.cxx:100
 TQSample.cxx:101
 TQSample.cxx:102
 TQSample.cxx:103
 TQSample.cxx:104
 TQSample.cxx:105
 TQSample.cxx:106
 TQSample.cxx:107
 TQSample.cxx:108
 TQSample.cxx:109
 TQSample.cxx:110
 TQSample.cxx:111
 TQSample.cxx:112
 TQSample.cxx:113
 TQSample.cxx:114
 TQSample.cxx:115
 TQSample.cxx:116
 TQSample.cxx:117
 TQSample.cxx:118
 TQSample.cxx:119
 TQSample.cxx:120
 TQSample.cxx:121
 TQSample.cxx:122
 TQSample.cxx:123
 TQSample.cxx:124
 TQSample.cxx:125
 TQSample.cxx:126
 TQSample.cxx:127
 TQSample.cxx:128
 TQSample.cxx:129
 TQSample.cxx:130
 TQSample.cxx:131
 TQSample.cxx:132
 TQSample.cxx:133
 TQSample.cxx:134
 TQSample.cxx:135
 TQSample.cxx:136
 TQSample.cxx:137
 TQSample.cxx:138
 TQSample.cxx:139
 TQSample.cxx:140
 TQSample.cxx:141
 TQSample.cxx:142
 TQSample.cxx:143
 TQSample.cxx:144
 TQSample.cxx:145
 TQSample.cxx:146
 TQSample.cxx:147
 TQSample.cxx:148
 TQSample.cxx:149
 TQSample.cxx:150
 TQSample.cxx:151
 TQSample.cxx:152
 TQSample.cxx:153
 TQSample.cxx:154
 TQSample.cxx:155
 TQSample.cxx:156
 TQSample.cxx:157
 TQSample.cxx:158
 TQSample.cxx:159
 TQSample.cxx:160
 TQSample.cxx:161
 TQSample.cxx:162
 TQSample.cxx:163
 TQSample.cxx:164
 TQSample.cxx:165
 TQSample.cxx:166
 TQSample.cxx:167
 TQSample.cxx:168
 TQSample.cxx:169
 TQSample.cxx:170
 TQSample.cxx:171
 TQSample.cxx:172
 TQSample.cxx:173
 TQSample.cxx:174
 TQSample.cxx:175
 TQSample.cxx:176
 TQSample.cxx:177
 TQSample.cxx:178
 TQSample.cxx:179
 TQSample.cxx:180
 TQSample.cxx:181
 TQSample.cxx:182
 TQSample.cxx:183
 TQSample.cxx:184
 TQSample.cxx:185
 TQSample.cxx:186
 TQSample.cxx:187
 TQSample.cxx:188
 TQSample.cxx:189
 TQSample.cxx:190
 TQSample.cxx:191
 TQSample.cxx:192
 TQSample.cxx:193
 TQSample.cxx:194
 TQSample.cxx:195
 TQSample.cxx:196
 TQSample.cxx:197
 TQSample.cxx:198
 TQSample.cxx:199
 TQSample.cxx:200
 TQSample.cxx:201
 TQSample.cxx:202
 TQSample.cxx:203
 TQSample.cxx:204
 TQSample.cxx:205
 TQSample.cxx:206
 TQSample.cxx:207
 TQSample.cxx:208
 TQSample.cxx:209
 TQSample.cxx:210
 TQSample.cxx:211
 TQSample.cxx:212
 TQSample.cxx:213
 TQSample.cxx:214
 TQSample.cxx:215
 TQSample.cxx:216
 TQSample.cxx:217
 TQSample.cxx:218
 TQSample.cxx:219
 TQSample.cxx:220
 TQSample.cxx:221
 TQSample.cxx:222
 TQSample.cxx:223
 TQSample.cxx:224
 TQSample.cxx:225
 TQSample.cxx:226
 TQSample.cxx:227
 TQSample.cxx:228
 TQSample.cxx:229
 TQSample.cxx:230
 TQSample.cxx:231
 TQSample.cxx:232
 TQSample.cxx:233
 TQSample.cxx:234
 TQSample.cxx:235
 TQSample.cxx:236
 TQSample.cxx:237
 TQSample.cxx:238
 TQSample.cxx:239
 TQSample.cxx:240
 TQSample.cxx:241
 TQSample.cxx:242
 TQSample.cxx:243
 TQSample.cxx:244
 TQSample.cxx:245
 TQSample.cxx:246
 TQSample.cxx:247
 TQSample.cxx:248
 TQSample.cxx:249
 TQSample.cxx:250
 TQSample.cxx:251
 TQSample.cxx:252
 TQSample.cxx:253
 TQSample.cxx:254
 TQSample.cxx:255
 TQSample.cxx:256
 TQSample.cxx:257
 TQSample.cxx:258
 TQSample.cxx:259
 TQSample.cxx:260
 TQSample.cxx:261
 TQSample.cxx:262
 TQSample.cxx:263
 TQSample.cxx:264
 TQSample.cxx:265
 TQSample.cxx:266
 TQSample.cxx:267
 TQSample.cxx:268
 TQSample.cxx:269
 TQSample.cxx:270
 TQSample.cxx:271
 TQSample.cxx:272
 TQSample.cxx:273
 TQSample.cxx:274
 TQSample.cxx:275
 TQSample.cxx:276
 TQSample.cxx:277
 TQSample.cxx:278
 TQSample.cxx:279
 TQSample.cxx:280
 TQSample.cxx:281
 TQSample.cxx:282
 TQSample.cxx:283
 TQSample.cxx:284
 TQSample.cxx:285
 TQSample.cxx:286
 TQSample.cxx:287
 TQSample.cxx:288
 TQSample.cxx:289
 TQSample.cxx:290
 TQSample.cxx:291
 TQSample.cxx:292
 TQSample.cxx:293
 TQSample.cxx:294
 TQSample.cxx:295
 TQSample.cxx:296
 TQSample.cxx:297
 TQSample.cxx:298
 TQSample.cxx:299
 TQSample.cxx:300
 TQSample.cxx:301
 TQSample.cxx:302
 TQSample.cxx:303
 TQSample.cxx:304
 TQSample.cxx:305
 TQSample.cxx:306
 TQSample.cxx:307
 TQSample.cxx:308
 TQSample.cxx:309
 TQSample.cxx:310
 TQSample.cxx:311
 TQSample.cxx:312
 TQSample.cxx:313
 TQSample.cxx:314
 TQSample.cxx:315
 TQSample.cxx:316
 TQSample.cxx:317
 TQSample.cxx:318
 TQSample.cxx:319
 TQSample.cxx:320
 TQSample.cxx:321
 TQSample.cxx:322
 TQSample.cxx:323
 TQSample.cxx:324
 TQSample.cxx:325
 TQSample.cxx:326
 TQSample.cxx:327
 TQSample.cxx:328
 TQSample.cxx:329
 TQSample.cxx:330
 TQSample.cxx:331
 TQSample.cxx:332
 TQSample.cxx:333
 TQSample.cxx:334
 TQSample.cxx:335
 TQSample.cxx:336
 TQSample.cxx:337
 TQSample.cxx:338
 TQSample.cxx:339
 TQSample.cxx:340
 TQSample.cxx:341
 TQSample.cxx:342
 TQSample.cxx:343
 TQSample.cxx:344
 TQSample.cxx:345
 TQSample.cxx:346
 TQSample.cxx:347
 TQSample.cxx:348
 TQSample.cxx:349
 TQSample.cxx:350
 TQSample.cxx:351
 TQSample.cxx:352
 TQSample.cxx:353
 TQSample.cxx:354
 TQSample.cxx:355
 TQSample.cxx:356
 TQSample.cxx:357
 TQSample.cxx:358
 TQSample.cxx:359
 TQSample.cxx:360
 TQSample.cxx:361
 TQSample.cxx:362
 TQSample.cxx:363
 TQSample.cxx:364
 TQSample.cxx:365
 TQSample.cxx:366
 TQSample.cxx:367
 TQSample.cxx:368
 TQSample.cxx:369
 TQSample.cxx:370
 TQSample.cxx:371
 TQSample.cxx:372
 TQSample.cxx:373
 TQSample.cxx:374
 TQSample.cxx:375
 TQSample.cxx:376
 TQSample.cxx:377
 TQSample.cxx:378
 TQSample.cxx:379
 TQSample.cxx:380
 TQSample.cxx:381
 TQSample.cxx:382
 TQSample.cxx:383
 TQSample.cxx:384
 TQSample.cxx:385
 TQSample.cxx:386
 TQSample.cxx:387
 TQSample.cxx:388
 TQSample.cxx:389
 TQSample.cxx:390
 TQSample.cxx:391
 TQSample.cxx:392
 TQSample.cxx:393
 TQSample.cxx:394
 TQSample.cxx:395
 TQSample.cxx:396
 TQSample.cxx:397
 TQSample.cxx:398
 TQSample.cxx:399
 TQSample.cxx:400
 TQSample.cxx:401
 TQSample.cxx:402
 TQSample.cxx:403
 TQSample.cxx:404
 TQSample.cxx:405
 TQSample.cxx:406
 TQSample.cxx:407
 TQSample.cxx:408
 TQSample.cxx:409
 TQSample.cxx:410
 TQSample.cxx:411
 TQSample.cxx:412
 TQSample.cxx:413
 TQSample.cxx:414
 TQSample.cxx:415
 TQSample.cxx:416
 TQSample.cxx:417
 TQSample.cxx:418
 TQSample.cxx:419
 TQSample.cxx:420
 TQSample.cxx:421
 TQSample.cxx:422
 TQSample.cxx:423
 TQSample.cxx:424
 TQSample.cxx:425
 TQSample.cxx:426
 TQSample.cxx:427
 TQSample.cxx:428
 TQSample.cxx:429
 TQSample.cxx:430
 TQSample.cxx:431
 TQSample.cxx:432
 TQSample.cxx:433
 TQSample.cxx:434
 TQSample.cxx:435
 TQSample.cxx:436
 TQSample.cxx:437
 TQSample.cxx:438
 TQSample.cxx:439
 TQSample.cxx:440
 TQSample.cxx:441
 TQSample.cxx:442
 TQSample.cxx:443
 TQSample.cxx:444
 TQSample.cxx:445
 TQSample.cxx:446
 TQSample.cxx:447
 TQSample.cxx:448
 TQSample.cxx:449
 TQSample.cxx:450
 TQSample.cxx:451
 TQSample.cxx:452
 TQSample.cxx:453
 TQSample.cxx:454
 TQSample.cxx:455
 TQSample.cxx:456
 TQSample.cxx:457
 TQSample.cxx:458
 TQSample.cxx:459
 TQSample.cxx:460
 TQSample.cxx:461
 TQSample.cxx:462
 TQSample.cxx:463
 TQSample.cxx:464
 TQSample.cxx:465
 TQSample.cxx:466
 TQSample.cxx:467
 TQSample.cxx:468
 TQSample.cxx:469
 TQSample.cxx:470
 TQSample.cxx:471
 TQSample.cxx:472
 TQSample.cxx:473
 TQSample.cxx:474
 TQSample.cxx:475
 TQSample.cxx:476
 TQSample.cxx:477
 TQSample.cxx:478
 TQSample.cxx:479
 TQSample.cxx:480
 TQSample.cxx:481
 TQSample.cxx:482
 TQSample.cxx:483
 TQSample.cxx:484
 TQSample.cxx:485
 TQSample.cxx:486
 TQSample.cxx:487
 TQSample.cxx:488
 TQSample.cxx:489
 TQSample.cxx:490
 TQSample.cxx:491
 TQSample.cxx:492
 TQSample.cxx:493
 TQSample.cxx:494
 TQSample.cxx:495
 TQSample.cxx:496
 TQSample.cxx:497
 TQSample.cxx:498
 TQSample.cxx:499
 TQSample.cxx:500
 TQSample.cxx:501
 TQSample.cxx:502
 TQSample.cxx:503
 TQSample.cxx:504
 TQSample.cxx:505
 TQSample.cxx:506
 TQSample.cxx:507
 TQSample.cxx:508
 TQSample.cxx:509
 TQSample.cxx:510
 TQSample.cxx:511
 TQSample.cxx:512
 TQSample.cxx:513
 TQSample.cxx:514
 TQSample.cxx:515
 TQSample.cxx:516
 TQSample.cxx:517
 TQSample.cxx:518
 TQSample.cxx:519
 TQSample.cxx:520
 TQSample.cxx:521
 TQSample.cxx:522
 TQSample.cxx:523
 TQSample.cxx:524
 TQSample.cxx:525
 TQSample.cxx:526
 TQSample.cxx:527
 TQSample.cxx:528
 TQSample.cxx:529
 TQSample.cxx:530
 TQSample.cxx:531
 TQSample.cxx:532
 TQSample.cxx:533
 TQSample.cxx:534
 TQSample.cxx:535
 TQSample.cxx:536
 TQSample.cxx:537
 TQSample.cxx:538
 TQSample.cxx:539
 TQSample.cxx:540
 TQSample.cxx:541
 TQSample.cxx:542
 TQSample.cxx:543
 TQSample.cxx:544
 TQSample.cxx:545
 TQSample.cxx:546
 TQSample.cxx:547
 TQSample.cxx:548
 TQSample.cxx:549
 TQSample.cxx:550
 TQSample.cxx:551
 TQSample.cxx:552
 TQSample.cxx:553
 TQSample.cxx:554
 TQSample.cxx:555
 TQSample.cxx:556
 TQSample.cxx:557
 TQSample.cxx:558
 TQSample.cxx:559
 TQSample.cxx:560
 TQSample.cxx:561
 TQSample.cxx:562
 TQSample.cxx:563
 TQSample.cxx:564
 TQSample.cxx:565
 TQSample.cxx:566
 TQSample.cxx:567
 TQSample.cxx:568
 TQSample.cxx:569
 TQSample.cxx:570
 TQSample.cxx:571
 TQSample.cxx:572
 TQSample.cxx:573
 TQSample.cxx:574
 TQSample.cxx:575
 TQSample.cxx:576
 TQSample.cxx:577
 TQSample.cxx:578
 TQSample.cxx:579
 TQSample.cxx:580
 TQSample.cxx:581
 TQSample.cxx:582
 TQSample.cxx:583
 TQSample.cxx:584
 TQSample.cxx:585
 TQSample.cxx:586
 TQSample.cxx:587
 TQSample.cxx:588
 TQSample.cxx:589
 TQSample.cxx:590
 TQSample.cxx:591
 TQSample.cxx:592
 TQSample.cxx:593
 TQSample.cxx:594
 TQSample.cxx:595
 TQSample.cxx:596
 TQSample.cxx:597
 TQSample.cxx:598
 TQSample.cxx:599
 TQSample.cxx:600
 TQSample.cxx:601
 TQSample.cxx:602
 TQSample.cxx:603
 TQSample.cxx:604
 TQSample.cxx:605
 TQSample.cxx:606
 TQSample.cxx:607
 TQSample.cxx:608
 TQSample.cxx:609
 TQSample.cxx:610
 TQSample.cxx:611
 TQSample.cxx:612
 TQSample.cxx:613
 TQSample.cxx:614
 TQSample.cxx:615
 TQSample.cxx:616
 TQSample.cxx:617
 TQSample.cxx:618
 TQSample.cxx:619
 TQSample.cxx:620
 TQSample.cxx:621
 TQSample.cxx:622
 TQSample.cxx:623
 TQSample.cxx:624
 TQSample.cxx:625
 TQSample.cxx:626
 TQSample.cxx:627
 TQSample.cxx:628
 TQSample.cxx:629
 TQSample.cxx:630
 TQSample.cxx:631
 TQSample.cxx:632
 TQSample.cxx:633
 TQSample.cxx:634
 TQSample.cxx:635
 TQSample.cxx:636
 TQSample.cxx:637
 TQSample.cxx:638
 TQSample.cxx:639
 TQSample.cxx:640
 TQSample.cxx:641
 TQSample.cxx:642
 TQSample.cxx:643
 TQSample.cxx:644
 TQSample.cxx:645
 TQSample.cxx:646
 TQSample.cxx:647
 TQSample.cxx:648
 TQSample.cxx:649
 TQSample.cxx:650
 TQSample.cxx:651
 TQSample.cxx:652
 TQSample.cxx:653
 TQSample.cxx:654
 TQSample.cxx:655
 TQSample.cxx:656
 TQSample.cxx:657
 TQSample.cxx:658
 TQSample.cxx:659
 TQSample.cxx:660
 TQSample.cxx:661
 TQSample.cxx:662
 TQSample.cxx:663
 TQSample.cxx:664
 TQSample.cxx:665
 TQSample.cxx:666
 TQSample.cxx:667
 TQSample.cxx:668
 TQSample.cxx:669
 TQSample.cxx:670
 TQSample.cxx:671
 TQSample.cxx:672
 TQSample.cxx:673
 TQSample.cxx:674
 TQSample.cxx:675
 TQSample.cxx:676
 TQSample.cxx:677
 TQSample.cxx:678
 TQSample.cxx:679
 TQSample.cxx:680
 TQSample.cxx:681
 TQSample.cxx:682
 TQSample.cxx:683
 TQSample.cxx:684
 TQSample.cxx:685
 TQSample.cxx:686
 TQSample.cxx:687
 TQSample.cxx:688
 TQSample.cxx:689
 TQSample.cxx:690
 TQSample.cxx:691
 TQSample.cxx:692
 TQSample.cxx:693
 TQSample.cxx:694
 TQSample.cxx:695
 TQSample.cxx:696
 TQSample.cxx:697
 TQSample.cxx:698
 TQSample.cxx:699
 TQSample.cxx:700
 TQSample.cxx:701
 TQSample.cxx:702
 TQSample.cxx:703
 TQSample.cxx:704
 TQSample.cxx:705
 TQSample.cxx:706
 TQSample.cxx:707
 TQSample.cxx:708
 TQSample.cxx:709
 TQSample.cxx:710
 TQSample.cxx:711
 TQSample.cxx:712
 TQSample.cxx:713
 TQSample.cxx:714
 TQSample.cxx:715
 TQSample.cxx:716
 TQSample.cxx:717
 TQSample.cxx:718
 TQSample.cxx:719
 TQSample.cxx:720
 TQSample.cxx:721
 TQSample.cxx:722
 TQSample.cxx:723
 TQSample.cxx:724
 TQSample.cxx:725
 TQSample.cxx:726
 TQSample.cxx:727
 TQSample.cxx:728
 TQSample.cxx:729
 TQSample.cxx:730
 TQSample.cxx:731
 TQSample.cxx:732
 TQSample.cxx:733
 TQSample.cxx:734
 TQSample.cxx:735
 TQSample.cxx:736
 TQSample.cxx:737
 TQSample.cxx:738
 TQSample.cxx:739
 TQSample.cxx:740
 TQSample.cxx:741
 TQSample.cxx:742
 TQSample.cxx:743
 TQSample.cxx:744
 TQSample.cxx:745
 TQSample.cxx:746
 TQSample.cxx:747
 TQSample.cxx:748
 TQSample.cxx:749
 TQSample.cxx:750
 TQSample.cxx:751
 TQSample.cxx:752
 TQSample.cxx:753
 TQSample.cxx:754
 TQSample.cxx:755
 TQSample.cxx:756
 TQSample.cxx:757
 TQSample.cxx:758
 TQSample.cxx:759
 TQSample.cxx:760
 TQSample.cxx:761
 TQSample.cxx:762
 TQSample.cxx:763
 TQSample.cxx:764
 TQSample.cxx:765
 TQSample.cxx:766
 TQSample.cxx:767
 TQSample.cxx:768
 TQSample.cxx:769
 TQSample.cxx:770
 TQSample.cxx:771
 TQSample.cxx:772
 TQSample.cxx:773
 TQSample.cxx:774
 TQSample.cxx:775
 TQSample.cxx:776
 TQSample.cxx:777
 TQSample.cxx:778
 TQSample.cxx:779
 TQSample.cxx:780
 TQSample.cxx:781
 TQSample.cxx:782
 TQSample.cxx:783
 TQSample.cxx:784
 TQSample.cxx:785
 TQSample.cxx:786
 TQSample.cxx:787
 TQSample.cxx:788
 TQSample.cxx:789
 TQSample.cxx:790
 TQSample.cxx:791
 TQSample.cxx:792
 TQSample.cxx:793
 TQSample.cxx:794
 TQSample.cxx:795
 TQSample.cxx:796
 TQSample.cxx:797
 TQSample.cxx:798
 TQSample.cxx:799
 TQSample.cxx:800
 TQSample.cxx:801
 TQSample.cxx:802
 TQSample.cxx:803
 TQSample.cxx:804
 TQSample.cxx:805
 TQSample.cxx:806
 TQSample.cxx:807
 TQSample.cxx:808
 TQSample.cxx:809
 TQSample.cxx:810
 TQSample.cxx:811
 TQSample.cxx:812
 TQSample.cxx:813
 TQSample.cxx:814
 TQSample.cxx:815
 TQSample.cxx:816
 TQSample.cxx:817
 TQSample.cxx:818
 TQSample.cxx:819
 TQSample.cxx:820
 TQSample.cxx:821
 TQSample.cxx:822
 TQSample.cxx:823
 TQSample.cxx:824
 TQSample.cxx:825
 TQSample.cxx:826
 TQSample.cxx:827
 TQSample.cxx:828
 TQSample.cxx:829
 TQSample.cxx:830
 TQSample.cxx:831
 TQSample.cxx:832
 TQSample.cxx:833
 TQSample.cxx:834
 TQSample.cxx:835
 TQSample.cxx:836
 TQSample.cxx:837
 TQSample.cxx:838
 TQSample.cxx:839
 TQSample.cxx:840
 TQSample.cxx:841
 TQSample.cxx:842
 TQSample.cxx:843
 TQSample.cxx:844
 TQSample.cxx:845
 TQSample.cxx:846
 TQSample.cxx:847
 TQSample.cxx:848
 TQSample.cxx:849
 TQSample.cxx:850
 TQSample.cxx:851
 TQSample.cxx:852
 TQSample.cxx:853
 TQSample.cxx:854
 TQSample.cxx:855
 TQSample.cxx:856
 TQSample.cxx:857
 TQSample.cxx:858
 TQSample.cxx:859
 TQSample.cxx:860
 TQSample.cxx:861
 TQSample.cxx:862
 TQSample.cxx:863
 TQSample.cxx:864
 TQSample.cxx:865
 TQSample.cxx:866
 TQSample.cxx:867
 TQSample.cxx:868
 TQSample.cxx:869
 TQSample.cxx:870
 TQSample.cxx:871
 TQSample.cxx:872
 TQSample.cxx:873
 TQSample.cxx:874
 TQSample.cxx:875
 TQSample.cxx:876
 TQSample.cxx:877
 TQSample.cxx:878
 TQSample.cxx:879
 TQSample.cxx:880
 TQSample.cxx:881
 TQSample.cxx:882
 TQSample.cxx:883
 TQSample.cxx:884
 TQSample.cxx:885
 TQSample.cxx:886
 TQSample.cxx:887
 TQSample.cxx:888
 TQSample.cxx:889
 TQSample.cxx:890
 TQSample.cxx:891
 TQSample.cxx:892
 TQSample.cxx:893
 TQSample.cxx:894
 TQSample.cxx:895
 TQSample.cxx:896
 TQSample.cxx:897
 TQSample.cxx:898
 TQSample.cxx:899
 TQSample.cxx:900
 TQSample.cxx:901
 TQSample.cxx:902
 TQSample.cxx:903
 TQSample.cxx:904
 TQSample.cxx:905
 TQSample.cxx:906
 TQSample.cxx:907
 TQSample.cxx:908
 TQSample.cxx:909
 TQSample.cxx:910
 TQSample.cxx:911
 TQSample.cxx:912
 TQSample.cxx:913
 TQSample.cxx:914
 TQSample.cxx:915
 TQSample.cxx:916
 TQSample.cxx:917
 TQSample.cxx:918
 TQSample.cxx:919
 TQSample.cxx:920
 TQSample.cxx:921
 TQSample.cxx:922
 TQSample.cxx:923
 TQSample.cxx:924
 TQSample.cxx:925
 TQSample.cxx:926
 TQSample.cxx:927
 TQSample.cxx:928
 TQSample.cxx:929
 TQSample.cxx:930
 TQSample.cxx:931
 TQSample.cxx:932
 TQSample.cxx:933
 TQSample.cxx:934
 TQSample.cxx:935
 TQSample.cxx:936
 TQSample.cxx:937
 TQSample.cxx:938
 TQSample.cxx:939
 TQSample.cxx:940
 TQSample.cxx:941
 TQSample.cxx:942
 TQSample.cxx:943
 TQSample.cxx:944
 TQSample.cxx:945
 TQSample.cxx:946
 TQSample.cxx:947
 TQSample.cxx:948
 TQSample.cxx:949
 TQSample.cxx:950
 TQSample.cxx:951
 TQSample.cxx:952
 TQSample.cxx:953
 TQSample.cxx:954
 TQSample.cxx:955
 TQSample.cxx:956
 TQSample.cxx:957
 TQSample.cxx:958
 TQSample.cxx:959
 TQSample.cxx:960
 TQSample.cxx:961
 TQSample.cxx:962
 TQSample.cxx:963
 TQSample.cxx:964
 TQSample.cxx:965
 TQSample.cxx:966
 TQSample.cxx:967
 TQSample.cxx:968
 TQSample.cxx:969
 TQSample.cxx:970
 TQSample.cxx:971
 TQSample.cxx:972
 TQSample.cxx:973
 TQSample.cxx:974
 TQSample.cxx:975
 TQSample.cxx:976
 TQSample.cxx:977
 TQSample.cxx:978
 TQSample.cxx:979
 TQSample.cxx:980
 TQSample.cxx:981
 TQSample.cxx:982
 TQSample.cxx:983
 TQSample.cxx:984
 TQSample.cxx:985
 TQSample.cxx:986
 TQSample.cxx:987
 TQSample.cxx:988
 TQSample.cxx:989
 TQSample.cxx:990
 TQSample.cxx:991
 TQSample.cxx:992
 TQSample.cxx:993
 TQSample.cxx:994
 TQSample.cxx:995
 TQSample.cxx:996
 TQSample.cxx:997
 TQSample.cxx:998
 TQSample.cxx:999
 TQSample.cxx:1000
 TQSample.cxx:1001
 TQSample.cxx:1002
 TQSample.cxx:1003
 TQSample.cxx:1004
 TQSample.cxx:1005
 TQSample.cxx:1006
 TQSample.cxx:1007
 TQSample.cxx:1008
 TQSample.cxx:1009
 TQSample.cxx:1010
 TQSample.cxx:1011
 TQSample.cxx:1012
 TQSample.cxx:1013
 TQSample.cxx:1014
 TQSample.cxx:1015
 TQSample.cxx:1016
 TQSample.cxx:1017
 TQSample.cxx:1018
 TQSample.cxx:1019
 TQSample.cxx:1020
 TQSample.cxx:1021
 TQSample.cxx:1022
 TQSample.cxx:1023
 TQSample.cxx:1024
 TQSample.cxx:1025
 TQSample.cxx:1026
 TQSample.cxx:1027
 TQSample.cxx:1028
 TQSample.cxx:1029
 TQSample.cxx:1030
 TQSample.cxx:1031
 TQSample.cxx:1032
 TQSample.cxx:1033
 TQSample.cxx:1034
 TQSample.cxx:1035
 TQSample.cxx:1036
 TQSample.cxx:1037
 TQSample.cxx:1038
 TQSample.cxx:1039