#include "QFramework/TQPlotter.h"

#include "TDirectory.h"
#include "TH1.h"
#include "TH2.h"
#include "TH2.h"
#include "TH3.h"
#include "TProfile.h"
#include "TMath.h"
#include "TGraphAsymmErrors.h"
#include "TGraphErrors.h"
#include "TObjArray.h"

// #define _DEBUG_

#include "QFramework/TQIterator.h"
#include "QFramework/TQLibrary.h"
#include "QFramework/TQNamedTaggable.h"
#include "QFramework/TQHistogramUtils.h"
#include "QFramework/TQStringUtils.h"
#include "QFramework/TQUtils.h"

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

#define DEFAULTTEXTSIZE 0.04
////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQPlotter:
//
// The abstract TQPlotter class provides a base class for custom plotters.
// By inheriting from the TQPlotter, a base data management interface is provided.
// For plotting with the ROOT graphics interface, refer to TQROOTPlotter.
//
////////////////////////////////////////////////////////////////////////////////////////////////

ClassImp(TQPlotter)

//__________________________________________________________________________________|___________

TQPlotter::TQPlotter() :
TQPresenter(),
  objects(new TDirectory("plotter_tmp",""))
{
  // Constructor of TQPlotter class
}

//__________________________________________________________________________________|___________

TQPlotter::TQPlotter(TQSampleFolder * baseSampleFolder) :
  TQPresenter(baseSampleFolder),
  objects(new TDirectory("plotter_tmp",""))
{
  // Constructor of TQPlotter class
}

//__________________________________________________________________________________|___________

TQPlotter::TQPlotter(TQSampleDataReader * dataSource) :
  TQPresenter(dataSource),
  objects(new TDirectory("plotter_tmp",""))
{
  // Constructor of TQPlotter class
}


//__________________________________________________________________________________|___________

void TQPlotter::reset() {
  TQPresenter::reset();

  // Reset the plotter
  this->clearObjects();
}

//__________________________________________________________________________________|___________

TString TQPlotter::makeHistogramIdentifier(TQNamedTaggable* process){
  TString name = process->getTagStringDefault(".name",process->getTagStringDefault("name",process->GetName()));
  if(TQStringUtils::isEmpty(name) || process->getTagBoolDefault(".ignoreProcessName",false)){
    return "hist_"+TQStringUtils::makeValidIdentifier(process->exportTagsAsString(),
                                                      TQStringUtils::letters+TQStringUtils::numerals+"_","_");
  } else {
    return "hist_"+TQStringUtils::makeValidIdentifier(name,
                                                      TQStringUtils::letters+TQStringUtils::numerals+"_","_");
  }
}

//__________________________________________________________________________________|___________

bool TQPlotter::addData(TString path, TString options) {
  // add a new data process to the plotter
  TQNamedTaggable* data = new TQNamedTaggable(path);
  data->setTagBool(".isData",true);
  data->setTagString(".legendOptions","lep");
  data->setTagString(".path",path);
  data->importTags(options,true);
  this->fProcesses->Add(data);
  return true;
}


//__________________________________________________________________________________|___________

bool TQPlotter::addBackground(TString path, TString options) {
  // add a new background process to the plotter
  TQNamedTaggable* bkg = new TQNamedTaggable(path);
  bkg->setTagBool(".isBackground",true);
  bkg->setTagString(".path",path);
  bkg->importTags(options,true);
  this->fProcesses->Add(bkg);
  return true;
}


//__________________________________________________________________________________|___________

bool TQPlotter::addSignal(TString path, TString options) {
  // add a new signal process to the plotter
  TQNamedTaggable* sig = new TQNamedTaggable(path);
  sig->setTagBool(".isSignal",true);
  sig->setTagString(".path",path);
  sig->importTags(options,true);
  this->fProcesses->Add(sig);
  return true;
}

//__________________________________________________________________________________|___________

TString TQPlotter::getScaleFactorList(TString histname){
  // retrieve a comma-separated list of the scaled contributions (titles only)
  TString cutname;
  if(!TQStringUtils::readUpTo(histname,cutname,"/")) return "";
  if(!this->getNormalizationInfo()) return "";
  TQFolder* f = this->getNormalizationInfo()->getFolder(TString::Format(".cut.%s",cutname.Data()));
  if(!f) return "";
  TString retval = "";
  TQIterator itr(f->getListOfKeys(),true);
  while(itr.hasNext()){
    TObject* obj = itr.readNext();
    if(!obj) continue;
    if(!retval.IsNull()) retval.Append(",");
    retval.Append(f->getTagStringDefault(obj->GetName(),obj->GetName()));
  }
  return retval;
}

//__________________________________________________________________________________|___________

bool TQPlotter::includeSystematics(TQTaggable& tags){
  // include the systematics entry from the systematics folder
  TString sysID = "";
  bool verbose = tags.getTagBoolDefault("verbose",false);
  bool showSys = tags.getTagString("errors.showSys",sysID);
  if(!showSys){
    if(verbose) VERBOSEclass("no showSys tag set, quitting");
    return false;
  }
  TQFolder* sysFolder = this->fSystematics->getFolder(sysID);
  if(!sysFolder){
    if(verbose){
      VERBOSEclass("unable to retrieve systematics folder '%s'",sysID.Data());
      this->fSystematics->print();
    }
    return false;
  } else {
    if(verbose) VERBOSEclass("successfully retrieved systematics folder '%s'",sysID.Data());
  }
  TString sourcename = tags.getTagStringDefault("errors.source","totalStack");
  TString targetname = tags.getTagStringDefault("errors.shiftTo",sourcename);
  TH1* hTotalBkg = this->getObject<TH1>(sourcename);
  if(!hTotalBkg){
    if(verbose) VERBOSEclass("unable to retrieve totalStack histogram!");
    return false;
  }
  TH1* hSys = TQPlotter::includeSystematics(hTotalBkg,sysFolder,tags);
  if(hSys){
    hSys->SetName(targetname+"Sys");
    // this->addObject(hSys); // (***): hSys is already in this->objects via copying - see comment (+++)
    return true;
  }
  return false;
}

//__________________________________________________________________________________|___________

TH1* TQPlotter::includeSystematics(const TH1* hTotalBkg,TQFolder* sysFolder, TQTaggable& tags){
  bool verbose = tags.getTagBoolDefault("verbose",false);  
  bool normSys = tags.getTagBoolDefault("errors.normSys",true);
  bool shapeSys = tags.getTagBoolDefault("errors.shapeSys",true);
  TString histName = tags.getTagStringDefault("input.sys",tags.getTagStringDefault("input.histogram"));
  TString cutname = TQFolder::getPathHead(histName);
  TQFolder* cutfolder= sysFolder->getFolder(cutname);
  if(!cutfolder) cutfolder = sysFolder;
  if (!cutfolder->hasTag("~yield") && !cutfolder->getTagBoolDefault("~shapeIncludesNormalization",true)) {
    ERRORclass("unable to retrieve normalization systematic for '%s/%s'.", cutname.Data(), histName.Data());
    return NULL;
  }
  TH1* hSys = TQHistogramUtils::copyHistogram(hTotalBkg); // (+++): hSys is already in this->objects via copying - see comment (***)
  double sys = cutfolder->getTagDoubleDefault("~yield",0);
  bool done = false;
  if (shapeSys){
    TH1* hSysRel = dynamic_cast<TH1*>(cutfolder->getObject(histName));
    bool histosConsistent = TQHistogramUtils::checkConsistency(hTotalBkg,hSysRel,verbose);
    if(hSysRel && histosConsistent){
      hSys->Multiply(hSysRel);
      bool shapeIncludesNorm = cutfolder->getTagBoolDefault("~shapeIncludesNormalization",true);
      if(shapeIncludesNorm != normSys){
        double factor = normSys ? 1 : -1;
        TQHistogramUtils::addHistogramInQuadrature(hSys,hTotalBkg,factor*sys*sys);
      }
      done = true;
    } else if(hSysRel){
      WARNclass("nominal and systematics histograms are inconsistent, disabling shape systematic!");
    } else {
      WARNclass("systematics histogram '%s' not found, disabling shape systematic!",histName.Data());
    }
  }
  if(!done && normSys){
    hSys->Scale(sys);
  }
  if(verbose) VERBOSEclass("successfully created total background systematics histogram '%s' with integral '%f'",hSys->GetName(),TQHistogramUtils::getIntegral(hSys));
  return hSys;
}

//__________________________________________________________________________________|___________

TObjArray * TQPlotter::getHistograms(TObjArray* processes, const TString& tagFilter, const TString& histName, const TString& namePrefix, TQTaggable& aliases,TQTaggable& options){
  // retrieve histograms using the internal reader
  // histogram options can be controlled by tags

  // stop if the reader is invalid
  if (!fReader) return 0;
  if(processes->GetEntries() == 0){
    ERRORclass("no processes given!");
    return 0;
  }

  bool verbose = options.getTagBoolDefault("verbose",false);

  // create the list of histograms
  TObjArray * histograms = new TObjArray();


  // loop over the list of processes and get histograms
  int i = 0;
  TQTaggableIterator itr(processes);
  while(itr.hasNext()){
    /* get the process properties */
    TQNamedTaggable * process = itr.readNext();
    if(!process) continue;
    if(!process->getTagBoolDefault(tagFilter,false)){
      if(verbose) VERBOSEclass(TString::Format("process '%s' not selected!",process->GetName()));
      continue;
    }
    i++;

    // get the path of the histogram
    TString path = process->getTagStringDefault(".path", "");
    path = aliases.replaceInText(path);

    // check for a predefined histogram name in the process info
    TString histogramName = process->replaceInText(process->getTagStringDefault("input",histName));
    histogramName = aliases.replaceInText(process->getTagStringDefault("input",histogramName));

    if (path.IsNull() || histogramName.IsNull()){
      if(verbose) VERBOSEclass("skipping histogram '%s' from '%s'",histogramName.Data(),path.Data());
      continue;
    }

    TQTaggable histoOptions;
    if (!namePrefix.IsNull()) {
      histoOptions.setTagString("prefix.name", namePrefix);
    }
    //the order of the following two lines is important, since TQTaggable::exportTags does not overwrite existing tags. However it is desirable to prioritize process specific tags over global ones.
    // import process specific options
    process->exportTags(&histoOptions);
    // import global options
    options.exportTags(&histoOptions);


    // get the histogram
    if(verbose) VERBOSEclass("retrieving histogram '%s' from '%s' with options '%s''",histogramName.Data(),path.Data(),histoOptions.exportTagsAsString().Data());
    TH1 * histo = fReader->getHistogram(path, histogramName, &histoOptions);
    if(histo){
      this->addObject(histo,this->makeHistogramIdentifier(process));
      TString histTitle = "";
      if(process->getTagString(".title",histTitle) || process->getTagString("title",histTitle)) histo->SetTitle(histTitle);
      TQHistogramUtils::applyStyle(histo,process);
      
      if (process->getTagBoolDefault("resetSumw2",false)) {
        histo->Sumw2(false);
      }
      
      if(TQUtils::isNum(TQHistogramUtils::getIntegral(histo))){
        histograms->Add(histo);
      } else {
        if(verbose) VERBOSEclass("histogram '%s' from '%s' is empty!'",histogramName.Data(),path.Data());
        delete histo;
      }
    } else if(verbose){
      VERBOSEclass("failed to retrieve histogram, skipping");
    }
  }

  /* return the list of histograms */
  return histograms;
}


//__________________________________________________________________________________|___________

bool TQPlotter::collectOptScanSimplifiedSystHistograms(std::vector<TH1*>& histos, TQTaggable& tags) {
  // collect one or multiple histograms based on a simplified systematics estimation
  // for use in optimizations (intended for optScan subplots). 
  // Note: caller has to take ownership of histograms being placed in the 
  // referenced vector<TH1*> !
  
  std::shared_ptr<TQTaggable> masterCfg = TQTaggable::getGlobalTaggable("master");
  //@tag: [significance.bkgErrorFromPath] This global("master") tag allows to specify a list of paths (including $(channel) and $(campaign) placeholders) to be used to determine a (systematic) uncertainty of the background estimate to be used with optScan subplots for FOMs which account for background uncertainties (for Poisson significance with background systematics see https://cds.cern.ch/record/2643488/files/ATL-COM-GEN-2018-026.pdf). The usual path arithmetics can be used to, e.g., define the error to be a fraction of some process' yield: "0.3*bkg/$(channel)/$(campaign)/fakes" . If multiple, comma seperated paths are given they are summed in quadrature to determine the full systematic uncertainty.
  std::vector<TString> bkgSystSources = masterCfg->getTagVString("significance.bkgErrorFromPath");
  bool allOK = true;
  if (bkgSystSources.size()>0) {
    TQTaggable inputTags;
    inputTags.importTagsWithoutPrefix(tags,"input.");
    TString histoName; 
    if (!inputTags.getTagString("name",histoName)) {
      ERRORclass("Failed to recover cut/histogram name, cannot determine systematic uncertainty for optScan!");
      //clean vector so caller can simply move on/return with error when something goes wrong
      for (TH1* h : histos) {
        delete h;
      }
      histos.clear();
      return false;
    }
    for (TString& systSource: bkgSystSources) { //on purpuse *not* const -> replace tags in place (channel, campaigns,...)
      systSource = inputTags.replaceInText(systSource);
      //we don't care about additional info here, so be a little faster and use getCounter directly...
      TH1* hist = fReader->getHistogram(systSource, histoName, &tags);
      if (!hist) {
        WARNclass( "Failed to obtain systematic uncertainty source histogram with path specification '%s' for distribution '%s'. Skipping this contribution!", systSource.Data(), histoName.Data() );
        allOK=false;
        continue;
      }
      histos.push_back(hist);
    }
  } 
  return allOK; 
}

//__________________________________________________________________________________|___________

bool TQPlotter::checkConsistency(TH1 * &hMaster, TObjArray * histograms) {
  // check the consistency of an array of histograms with the master histogram
  // will create the master histogram if not present

  TQIterator itr(histograms);
  while(itr.hasNext()){
    // iterate over list and check consistency of histograms
    TH1 * h = dynamic_cast<TH1*>(itr.readNext());
    if (!h) continue;
    if (hMaster) {
      if (!TQHistogramUtils::checkConsistency(hMaster, h) || TMath::IsNaN(TQHistogramUtils::getIntegral(h)))
        return false;
    } else {
      hMaster = TQHistogramUtils::copyHistogram(h,"Graph_master");
      hMaster->SetTitle("Main Coordinate System");
    }
  }

  /* return if histograms are consistent */
  return true;
}

//__________________________________________________________________________________|___________

double TQPlotter::getHistogramUpperLimit(TQTaggable& tags, TList * histograms, double lower, bool includeErrors){
  // calculate the "blocks" (x-axis ranges and corresponding y-values)
  // these are employed to avoid collisions of the bins with labels and other graphic elements (i.e. the legend)

  if (!histograms)
    return 0;

  bool logScale = tags.getTagBoolDefault ("style.logScale",false );

  double left = 0;
  double maxUpperLimit = 0.;

  int iBlock = 0;
  double block_x = 0;
  double block_y = 100;

  TH1* exampleHist = dynamic_cast<TH1*>(histograms->At(0));
  double xmin = TQHistogramUtils::getAxisXmin(exampleHist);
  double xmax = TQHistogramUtils::getAxisXmax(exampleHist);

  if(!(TQUtils::isNum(xmin) && TQUtils::isNum(xmax))) return std::numeric_limits<double>::quiet_NaN();
#ifdef _DEBUG_
  histograms->Print();
#endif

  while(tags.getTagDouble(TString::Format("blocks.x.%d",iBlock),block_x) && tags.getTagDouble(TString::Format("blocks.y.%d",iBlock),block_y)){
    double right = block_x;
    double vetoFrac = block_y;

    double block_min = xmin+left*(xmax-xmin);
    double block_max = xmin+right*(xmax-xmin);

    double max = TQHistogramUtils::getMaximumBinValue(histograms, block_min, block_max, includeErrors);

    double upperLimit = 0.;
    if (logScale) upperLimit =  exp(log(max/lower) / vetoFrac ) * lower;
    else          upperLimit = (max - lower) / vetoFrac + lower;


    if (upperLimit > maxUpperLimit) maxUpperLimit = upperLimit;
    left = right;
    iBlock++;
  }
  if(iBlock == 0){
    maxUpperLimit = TQHistogramUtils::getMaximumBinValue(histograms, xmin, xmax, includeErrors);
  }

  return maxUpperLimit;
}

//______________________________________________________________________________________________

bool TQPlotter::plotAndSaveAs(const TString& histogram, const TString& saveAs, const TString& inputTags) {
  // plot and save the given histogram using the given tags
  // the tags are forwarded to and interpreted by the makeplot function

  TQTaggable tags(inputTags);
  return this->plotAndSaveAs(histogram,saveAs,tags);
}

//______________________________________________________________________________________________

bool TQPlotter::plotAndSaveAs(const TString& histogram, const TString& saveAs, const char* inputTags) {
  // plot and save the given histogram using the given tags
  // the tags are forwarded to and interpreted by the makeplot function

  TQTaggable tags((const TString)(inputTags));
  return this->plotAndSaveAs(histogram,saveAs,tags);
}

//______________________________________________________________________________________________

bool TQPlotter::plotAndSaveAs(const TString& histogram, const TString& saveAs, TQTaggable& inputTags) {
  // plot and save the given histogram using the given tags
  // the tags are forwarded to and interpreted by the makeplot function
  return this->plotAndSaveAs(histogram,saveAs,&inputTags);
}


//______________________________________________________________________________________________

bool TQPlotter::plotAndSaveAs(const TString& histogram, const TString& saveAs, TQTaggable * inputTags) {
  // plot and save the given histogram using the given tags
  // the tags are forwarded to and interpreted by the makeplot function

  this->deleteObjects();
  this->clearObjects();

  TQTaggable tags(inputTags);
  tags.setGlobalOverwrite(false);
  tags.importTags(this);
  tags.setTagString(".saveAs",saveAs);

  bool verbose = tags.getTagBoolDefault("verbose",false);

  //@tags: ensureDirectory: create directories to ensure target path exists
  if(tags.getTagBoolDefault("ensureDirectory",false)){
    if(verbose) VERBOSEclass("ensuring directory");
    TQUtils::ensureDirectoryForFile(saveAs);
  }

  return plotAndSaveAsInternal(histogram,saveAs,tags);
}

//______________________________________________________________________________________________

TQPlotter::~TQPlotter() {
  // Destructor of TQPlotter class:
  // this->clearObjects();
  // if(this->objects) delete this->objects;
}

//__________________________________________________________________________________|___________

void TQPlotter::estimateRangeY(TH1* h, double& min, double &max, double tolerance){
  TGraphErrors * g = new TGraphErrors(h);
  estimateRangeY(g,min,max,tolerance);
  delete g;
}

//__________________________________________________________________________________|___________

void TQPlotter::estimateRangeY(TGraphErrors* g, double& min, double &max, double tolerance){
  // estimate the y-range of a TGraphErrors
  if(tolerance < 0) tolerance = std::numeric_limits<double>::infinity();
  if(g->GetN() < 1){
    // we can't estimate the range of an empty graph
    return;
  }
  if(g->GetN() < 2){
    // if there's only one point, that is the range;
    double x,y;
    g->GetPoint(0,x,y);
    min = y - g->GetErrorY(0);
    max = y + g->GetErrorY(0);
    return;
  }
  double sumwy = 0;
  double sumw = 0;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    double x, y;
    if( i != (size_t)(g->GetPoint((int)i, x, y))) continue;
    DEBUGclass("looking at point %d: x=%f, y=%f",(int)i,x,y);
    if(y < min) continue;
    if(y > max) continue;
    double err = g->GetErrorY(i);
    if(TQUtils::isNum(err) && err > 0){
      double w = pow(err,-2);
      sumw += w;
      sumwy += w*y;
    }
  }
  double ym = sumwy/sumw;
  DEBUGclass("found ym=%f (sumwy=%f, sumw=%f)", ym, sumwy, sumw);
  double sumsigma = 0;
  double sumw2 = 0;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    double x, y;
    if( i != (size_t)(g->GetPoint((int)i, x, y))) continue;
    if(y < min) continue;
    if(y > max) continue;
    double err = g->GetErrorY(i);
    if(TQUtils::isNum(err) && err > 0){
      double w = pow(err,-2);
      sumsigma += w * pow(y - ym,2);
      sumw2 += w*w;
    }
  }
  double sy2 = sumw / (sumw * sumw - sumw2) * sumsigma;
  double sy = sqrt(sy2);
  DEBUGclass("found sy2=%f, sy=%f",sy2,sy);


  double tmpmin = ym;
  double tmpmax = ym;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    double x, y;
    if( i != (size_t)(g->GetPoint((int)i, x, y))) continue;
    if(y > max) continue;
    if(y < min) continue;
    if(y > ym + tolerance * sy) continue;
    if(y < ym - tolerance * sy) continue;
    if(y > tmpmax) tmpmax = y+g->GetErrorY(i);
    if(y < tmpmin) tmpmin = y-g->GetErrorY(i);
  }
  min = tmpmin;
  max = tmpmax;
}


//__________________________________________________________________________________|___________


void TQPlotter::estimateRangeY(TGraphAsymmErrors* g, double& min, double &max, double tolerance){
  // estimate the y-range of a TGraphAsymmErrors
  if(tolerance < 0) tolerance = std::numeric_limits<double>::infinity();
  if(g->GetN() < 1){
    // we can't estimate the range of an empty graph
    return;
  }
  if(g->GetN() < 2){
    // if there's only one point, that is the range;
    double x,y;
    g->GetPoint(0,x,y);
    min = y - g->GetErrorYlow(0);
    max = y + g->GetErrorYhigh(0);
    return;
  }
  double sumwy = 0;
  double sumw = 0;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    double x, y;
    if( i != (size_t)(g->GetPoint((int)i, x, y))) continue;
    DEBUGclass("looking at point %d: x=%f, y=%f",(int)i,x,y);
    if(y < min) continue;
    if(y > max) continue;
    double err = sqrt(pow(g->GetErrorYlow(i),2)+pow(g->GetErrorYhigh(i),2));
    if(TQUtils::isNum(err) && err > 0){
      double w = pow(err,-2);
      sumw += w;
      sumwy += w*y;
    }
  }
  double ym = sumwy/sumw;
  DEBUGclass("found ym=%f (sumwy=%f, sumw=%f)", ym, sumwy, sumw);
  double sumsigma = 0;
  double sumw2 = 0;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    double x, y;
    if( i != (size_t)(g->GetPoint((int)i, x, y))) continue;
    if(y < min) continue;
    if(y > max) continue;
    double err = sqrt(pow(g->GetErrorYlow(i),2)+pow(g->GetErrorYhigh(i),2));
    if(TQUtils::isNum(err) && err > 0){
      double w = pow(err,-2);
      sumsigma += w * pow(y - ym,2);
      sumw2 += w*w;
    }
  }
  double sy2 = sumw / (sumw * sumw - sumw2) * sumsigma;
  double sy = sqrt(sy2);
  DEBUGclass("found sy2=%f, sy=%f",sy2,sy);


  double tmpmin = ym;
  double tmpmax = ym;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    double x, y;
    if( i != (size_t)(g->GetPoint((int)i, x, y))) continue;
    if(y > max) continue;
    if(y < min) continue;
    if(y > ym + tolerance * sy) continue;
    if(y < ym - tolerance * sy) continue;
    if(y > tmpmax) tmpmax = y+g->GetErrorY(i);
    if(y < tmpmin) tmpmin = y-g->GetErrorY(i);
  }
  min = tmpmin;
  max = tmpmax;
}


//__________________________________________________________________________________|___________

void TQPlotter::getRange(TGraphErrors* g, double &xlow, double &xhigh, double &ylow, double &yhigh, bool get_xrange, bool get_yrange, double maxQerr){
  // extract the range from a TGraphErrors
  if(maxQerr < 0) maxQerr = std::numeric_limits<double>::infinity();
  int nx = 0;
  int ny = 0;
  double x;
  double y;
  double sumx = 0;
  double sumx2 = 0;
  double sumy = 0;
  double sumy2 = 0;
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    if( i == (size_t)(g->GetPoint((int)i, x, y))){
      if((get_xrange || TQUtils::inRange(x, xlow , xhigh)) && (get_yrange || TQUtils::inRange(y, ylow , yhigh))){
        if(get_xrange){
          nx++;
          sumx += x;
          sumx2 += x*x;
        }
        if(get_yrange){
          ny++;
          sumy += y;
          sumy2 += y*y;
        }
      }
    }
  }
  double xmean = sumx/nx;
  double ymean = sumy/ny;
  double xvar = sumx2/nx - pow(sumx/nx,2);
  double yvar = sumy2/ny - pow(sumy/ny,2);
  for(size_t i=0; i < (size_t)(g->GetN()); i++){
    if( i == (size_t)(g->GetPoint((int)i, x, y))){
      if((get_xrange || TQUtils::inRange(x, xlow , xhigh)) && (get_yrange || TQUtils::inRange(y, ylow , yhigh))){
        if(get_xrange){
          if(!TQUtils::isNum(xlow)) xlow = xmean-sqrt(xvar);
          if(!TQUtils::isNum(xhigh)) xhigh = xmean+sqrt(xvar);
          double xm = 0.5*(xhigh + xlow);
          double xd = (xhigh-xlow);
          if(xd < 2*std::numeric_limits<double>::epsilon()) xd = std::numeric_limits<double>::infinity();
          if(TQUtils::inRange(x-g->GetErrorX(i),xm-(xd*maxQerr),xlow)) { xlow = x-g->GetErrorX(i); }
          if(TQUtils::inRange(x+g->GetErrorX(i),yhigh,xm+(xd*maxQerr))){ xhigh = x+g->GetErrorX(i); }
        }
        if(get_yrange){
          if(!TQUtils::isNum(ylow)) ylow = ymean-sqrt(yvar);
          if(!TQUtils::isNum(yhigh)) yhigh = ymean+sqrt(yvar);
          double ym = 0.5*(yhigh + ylow);
          double yd = (yhigh-ylow);
          if(yd < 2*std::numeric_limits<double>::epsilon()) yd = std::numeric_limits<double>::infinity();
          if(TQUtils::inRange(y-g->GetErrorY(i),ym-(yd*maxQerr),ylow)) { ylow = y-g->GetErrorY(i); }
          if(TQUtils::inRange(y+g->GetErrorY(i),yhigh,ym+(yd*maxQerr))){ yhigh = y+g->GetErrorY(i); }
        }
      }
    }
  }
}

//__________________________________________________________________________________|___________


void TQPlotter::applyErrors(const TH1* hSource, TH1* hTarget, const TH1* hSys, TQTaggable& tags){
  bool includeSys = tags.getTagBoolDefault("errors.drawSysMC", tags.hasTag("errors.showSys") || tags.hasTag("errors.totalBkgSys") );
  bool includeStat = tags.getTagBoolDefault("errors.drawStatMC", tags.getTagBoolDefault("errors.showStat", true ) );
  bool verbose = tags.getTagBoolDefault("verbose",false);  
  if (!includeStat) {
    /* set bin errors to zero */
    if(verbose) VERBOSEclass("removing statistical errors from total background histogram");
    TQHistogramUtils::resetBinErrors(hTarget);
  }
  
  if (includeSys){
    if (includeSys && !hSys && verbose) {
      VERBOSEclass("no total background systematics found");
    }
    /* include systematics */
    if(verbose) VERBOSEclass("adding systematic errors to total background histogram");
    for (int iBin = 1; iBin <= hSource->GetNbinsX(); iBin++) {
      double sysLin = 0.0;
      double sysSq = 0.0;
      double stat = hSource->GetBinError(iBin);
      if(hSys) {
        sysLin = hSys->GetBinContent(iBin);
        sysSq = hSys->GetBinError(iBin);
      }
      double total = TMath::Sqrt(stat*stat + sysLin*sysLin + sysSq*sysSq);
      hTarget->SetBinError(iBin, total);
    }
  }
}


//__________________________________________________________________________________|___________

void TQPlotter::setErrors(TQTaggable& tags, const TString& sourcename){
  // the histograms retrieved using the TQSampleDataReader class
  // have the statistical uncertainty filled into bin errors by default
  // this function either sets them to zero (for statMCerrors=false)
  // or adds the systematic uncertainties in quadrature (for sysMCerrors=true)
  bool verbose = tags.getTagBoolDefault("verbose",false);
  TString targetname = tags.getTagStringDefault("errors.shiftTo",sourcename);
  TH1* hSource = this->getObject<TH1>(sourcename);
  if(!hSource){
    if(verbose) VERBOSEclass("no total histogram named '%s' found",sourcename.Data());
    return;
  }
  TH1* hTarget = this->getObject<TH1>(targetname);
  TH1* hSys = this->getObject<TH1>(targetname+"Sys");
  TQPlotter::applyErrors(hSource,hTarget,hSys,tags);
}

//__________________________________________________________________________________|___________

void TQPlotter::addObject(TNamed* obj, const TString& key){
  // add an object to the list of graphics objects maintained by the plotter
  if(!obj) return;
  if(!key.IsNull()) obj->SetName(key);
  if(this->objects->FindObject(obj->GetName())){
    ERRORclass("cannot add object '%s' - an object of this name already exists!",obj->GetName());
  }
  this->objects->Add(obj);
}

//__________________________________________________________________________________|___________

void TQPlotter::addObject(TGraph* obj, TString key){
  // add an object to the list of graphics objects maintained by the plotter
  if(!obj) return;
  if(key.IsNull()) key = obj->GetName();
  obj->SetName("tmpgraph");
  obj->GetHistogram()->SetName(TString::Format("h_%s",key.Data()));
  obj->SetName(key.Data());
  if(this->objects->FindObject(obj->GetName())){
    ERRORclass("cannot add object '%s' - an object of this name already exists!",obj->GetName());
  }
  this->objects->Add(obj);
  obj->GetHistogram()->SetDirectory(NULL);
  DEBUGclass("%s@%#x <=> %s@%#x",obj->GetName(),this->objects,obj->GetHistogram()->GetName(),obj->GetHistogram()->GetDirectory());
}

//__________________________________________________________________________________|___________

void TQPlotter::addObject(TCollection* obj, const TString& key){
  // add a collection to the list of graphics objects maintained by the plotter
  if(!obj) return;
  if(!key.IsNull()) obj->SetName(key);
  this->objects->Add(obj);
}

//__________________________________________________________________________________|___________

void TQPlotter::addObject(TH1* obj, const TString& key){
  // add a histogram to the list of graphics objects maintained by the plotter
  if(!obj) return;
  if(!key.IsNull()) obj->SetName(key);
  if(this->objects->FindObject(obj->GetName())){
    ERRORclass("cannot add histogram '%s' - an object of this name already exists!",obj->GetName());
  }
  obj->SetDirectory(this->objects);
}

//__________________________________________________________________________________|___________

void TQPlotter::removeObject(const TString& key, bool deleteObject){
  // remove an object from the list of graphics object maintained by the plotter
  TObject* obj = this->objects->FindObject(key);
  if(!obj) return;
  this->objects->Remove(obj);
  if(deleteObject) delete obj;
}

//__________________________________________________________________________________|___________

void TQPlotter::clearObjects(){
  // clear all objects maintained by the plotter
  this->objects->Clear();
}

//__________________________________________________________________________________|___________

void TQPlotter::deleteObjects(){
  // clear all objects maintained by the plotter
  this->objects->DeleteAll();
  this->objects->Clear();
}

//__________________________________________________________________________________|___________

void TQPlotter::printObjects(){
  // print all objects maintained by the plotter
  TQIterator itr(this->objects->GetList());
  while(itr.hasNext()){
    TObject* obj = itr.readNext();
    if(!obj) continue;
    std::cout << TQStringUtils::makeBoldBlue(TQStringUtils::fixedWidth(obj->ClassName(),15));
    std::cout << " ";
    std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth(obj->GetName(),50,"l"));
    std::cout << " ";
    std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth(obj->GetTitle(),50,"l"));
    std::cout << " ";
    TGraph* g = dynamic_cast<TGraph*>(obj);
    if(g){
      std::cout << TQHistogramUtils::getDetailsAsString(g);
      if(TQStringUtils::matches(g->GetName(),"contour_*")) std::cout << ", contour area=" << fabs(TQHistogramUtils::getContourArea(g));
    } else if (obj->InheritsFrom(TH1::Class())) {
      std::cout << TQHistogramUtils::getDetailsAsString((TH1*)obj,4);
    } else {
      std::cout << TQStringUtils::getDetails(obj);
    }
    std::cout << std::endl;
  }
}

//__________________________________________________________________________________|___________

TObject* TQPlotter::getTObject(const TString& key){
  // retrieve a graphics object by name
  TQIterator itr(this->objects->GetList());
  while(itr.hasNext()){
    TObject* obj = itr.readNext();
    if(!obj) continue;
    if(TQStringUtils::matches(obj->GetName(),key)){
      return obj;
    }
  }
  return NULL;
}


//__________________________________________________________________________________|___________

void TQPlotter::applyStyle(TQTaggable& tags, TAxis* a, const TString& key, double/*distscaling*/, double/*sizescaling*/){
  // apply a tag-defined style to an axis
  // tags are read by the given key
  // sizes and distances are scaled according to the given parameters
  //@tags: style.*.showTitle: control whether axis title will be shown
  //@tags: style.*.showLabels: control whether axis labels will be shown
  //@tags: style.*.showTicks: control whether axis ticks
  //@tags: style.*.nDiv: number of divisions (encoded in 5 digit number, default 00510) for this axis
  if(!a) return;
  TString title;
  if(tags.getTagString("style."+key+".title",title)){
    a->SetTitle(title);
  }
  if(!tags.getTagBoolDefault("style."+key+".showTitle",true)){
    a->SetTitleOffset(0.);
    a->SetTitleSize (0.);
  }
  if(!tags.getTagBoolDefault("style."+key+".showLabels",true)){
    a->SetLabelOffset(0.);
    a->SetLabelSize (0.);
  }
  if(!tags.getTagBoolDefault("style."+key+".showTicks",true)){
    a->SetTickLength (0.);
  }
  if(!tags.getTagBoolDefault("style."+key+".allowExponent",true)){
    a->SetNoExponent(true);
  }
  int ndiv = 510;;
  if(tags.getTagInteger("style."+key+".nDiv",ndiv)){
    a->SetNdivisions(ndiv,!tags.getTagBoolDefault("style."+key+".nDiv.force",false));
  }
}

//__________________________________________________________________________________|___________

void TQPlotter::applyGeometry(TQTaggable& tags, TAxis* a, const TString& key, double thisdim, double otherdim, bool force){
  // apply a tag-defined geometry to an axis
  // tags are read by the given key
  // sizes and distances are scaled according to the given parameters
  //@tags: style.textSize: text size (default 0.05)
  //@tags: geometry.*.titleSize: title size (default:textSize)
  //@tags: geometry.*.labelSize: label size (default:textSize)
  //@tags: geometry.*.titleOffset: title offset
  //@tags: geometry.*.labelOffset: label offset
  //@tags: geometry.*.tickLength: label offset
  if(!a) return;
  double areascale = pow(thisdim*otherdim, 0.7);
  DEBUGclass("using areascale %f", areascale);
  double textSize = tags.getTagDoubleDefault("geometry.textSize",DEFAULTTEXTSIZE);
  double titleSize = tags.getTagDoubleDefault ("geometry.titleSize",textSize);
  // bool pixelText = tags.getTagBoolDefault("style.usePixelSize", false);
  int font = tags.getTagDoubleDefault("style.font",42);
  a->SetTitleFont(font);
  a->SetLabelFont(font);

  if ((font % 10) == 3) {         // don't scale the area if we're using pixels as font size
    DEBUGclass("don't scale the area, we're using a pixel font");
    areascale = 1;
  }
  if(tags.getTagDouble ("geometry."+key+".titleSize",titleSize) || force){
    a->SetTitleSize (titleSize*areascale);
    DEBUGclass("setting title size to %f", titleSize*areascale);
  }
  double titleoffset=tags.getTagDoubleDefault ("geometry.titleOffset", 1);
  if(tags.getTagDouble ("geometry."+key+".titleOffset", titleoffset) || force){
    a->SetTitleOffset(titleoffset / areascale);
    DEBUGclass("setting title offset to %f", titleoffset / areascale);
  }
  double labelSize = textSize;
  if(tags.getTagDouble ("geometry."+key+".labelSize",labelSize) || force){
    DEBUGclass("setting axis label size to %f", labelSize*areascale);
    a->SetLabelSize (labelSize*areascale);
  }
  double labelOffset = 0.005;
  if(tags.getTagDouble ("geometry."+key+".labelOffset",labelOffset) || force){
    a->SetLabelOffset(labelOffset);
  }
  double ticklength = tags.getTagDoubleDefault("geometry.tickLength",0.03);
  if(tags.getTagDouble ("geometry."+key+".tickLength",ticklength) || force){
    a->SetTickLength (ticklength*otherdim);
  }
}

//__________________________________________________________________________________|___________

void TQPlotter::applyGeometry(TQTaggable& tags, TH1* hist, const TString& key, double xscaling, double yscaling, bool force){
  // apply a tag-defined geometry to a histogram
  // tags are read by the given key
  // sizes and distances are scaled according to the given parameters
  if(!hist) return;
  
  tags.getTagDouble("geometry."+key+".xscaling",xscaling);
  tags.getTagDouble("geometry."+key+".yscaling",yscaling);  
  
  TAxis* xAxis = hist->GetXaxis(); 
  // *jedi move* you do not want to know of the handling of xscaling vs. yscaling
  applyGeometry(tags,xAxis,key+".xAxis",yscaling,yscaling,force);
  TAxis* yAxis = hist->GetYaxis();
  // *jedi move* you do not want to know of the handling of xscaling vs. yscaling
  applyGeometry(tags,yAxis,key+".yAxis",yscaling,xscaling,force);
}

//__________________________________________________________________________________|___________

void TQPlotter::applyGeometry(TQTaggable& tags, TGraph* g, const TString& key, double xscaling, double yscaling, bool force){
  // apply a tag-defined geometry to a graph
  // tags are read by the given key
  // sizes and distances are scaled according to the given parameters
  if(!g) return;

  tags.getTagDouble("geometry."+key+".xscaling",xscaling);
  tags.getTagDouble("geometry."+key+".yscaling",yscaling);

  TAxis* xAxis = g->GetXaxis();
  // *jedi move* you do not want to know of the handling of xscaling vs. yscaling
  applyGeometry(tags,xAxis,key+".xAxis",yscaling,yscaling, force);
  TAxis* yAxis = g->GetYaxis();
  // *jedi move* you do not want to know of the handling of xscaling vs. yscaling
  applyGeometry(tags,yAxis,key+".yAxis",yscaling,xscaling, force);
}

//__________________________________________________________________________________|___________

void TQPlotter::applyStyle(TQTaggable& tags, TH1* hist, const TString& key, double xscaling, double yscaling){
  // apply a tag-defined style to a histogram
  // tags are read by the given key
  // sizes and distances are scaled according to the given parameters
  //@tags: style.*.fillColor: set fill color using TH1::SetFillColor
  //@tags: style.*.fillStyle: set fill style using TH1::SetFillStyle
  //@tags: style.*.lineColor: set line color using TH1::SetLineColor
  //@tags: style.*.lineStyle: set line style using TH1::SetLineStyyle
  //@tags: style.*.markerColor: set marker color using TH1::SetMarkerColor
  //@tags: style.*.markerSize: set marker size using TH1::SetMarkerSize
  //@tags: style.*.markerStyle: set marker size using TH1::SetMarkerStyle
  if(!hist) return;
  TAxis* xAxis = hist->GetXaxis();
  // *jedi move* you do not want to know of the handling of xscaling vs. yscaling
  applyStyle(tags,xAxis,key+".xAxis",xscaling,yscaling);
  TAxis* yAxis = hist->GetYaxis();
  // *jedi move* you do not want to know of the handling of xscaling vs. yscaling
  applyStyle(tags,yAxis,key+".yAxis",xscaling,yscaling);
  int fillColor = hist->GetFillColor (); tags.getTagInteger("style."+key+".fillColor", fillColor); hist->SetFillColor (fillColor);
  int fillStyle = hist->GetFillStyle (); tags.getTagInteger("style."+key+".fillStyle", fillStyle); hist->SetFillStyle (fillStyle);
  int lineColor = hist->GetLineColor (); tags.getTagInteger("style."+key+".lineColor", lineColor); hist->SetLineColor (lineColor);
  double lineWidth = hist->GetLineWidth (); tags.getTagDouble ("style."+key+".lineWidth", lineWidth); hist->SetLineWidth (lineWidth);
  int lineStyle = hist->GetLineStyle (); tags.getTagInteger("style."+key+".lineStyle", lineStyle); hist->SetLineStyle (lineStyle);
  int markerColor = hist->GetMarkerColor(); tags.getTagInteger("style.markerColor",markerColor); tags.getTagInteger("style."+key+".markerColor", markerColor); hist->SetMarkerColor(markerColor);
  double markerSize = hist->GetMarkerSize (); tags.getTagDouble ("style.markerSize", markerSize ); tags.getTagDouble ("style."+key+".markerSize" , markerSize ); hist->SetMarkerSize (markerSize );
  int markerStyle = hist->GetMarkerStyle(); tags.getTagInteger("style.markerStyle",markerStyle); tags.getTagInteger("style."+key+".markerStyle", markerStyle); hist->SetMarkerStyle(markerStyle);
  if(tags.getTagBoolDefault ("style.binticks",false )){
    hist->GetXaxis()->SetNdivisions(hist->GetNbinsX(),0,0,false);
  }
}

//__________________________________________________________________________________|___________

void TQPlotter::applyStyle(TQTaggable& tags, TGraph* g, const TString& key, double xscaling, double yscaling){
  // apply a tag-defined style to a graph
  // tags are read by the given key
  // sizes and distances are scaled according to the given parameters
  if(!g) return;
  TAxis* xAxis = g->GetXaxis();
  applyStyle(tags,xAxis,key+".xAxis",xscaling,yscaling);
  TAxis* yAxis = g->GetYaxis();
  applyStyle(tags,yAxis,key+".yAxis",xscaling,yscaling);
  int fillColor = 0; if(tags.getTagInteger("style."+key+".fillColor", fillColor) || tags.getTagInteger("style.fillColor", fillColor)) g->SetFillColor(fillColor);
  int fillStyle = 0; if(tags.getTagInteger("style."+key+".fillStyle", fillStyle)  || tags.getTagInteger("style.fillStyle", fillStyle)) g->SetFillStyle(fillStyle);
  int lineColor = 0; if(tags.getTagInteger("style."+key+".lineColor", lineColor) || tags.getTagInteger("style.lineColor", lineColor)) g->SetLineColor(lineColor);
  int lineStyle = 0; if(tags.getTagInteger("style."+key+".lineStyle", lineStyle) || tags.getTagInteger("style.lineStyle", lineStyle)) g->SetLineStyle(lineStyle);
  double lineWidth = 0; if(tags.getTagDouble("style."+key+".lineWidth", lineWidth) || tags.getTagDouble("style.lineWidth", lineWidth)) g->SetLineWidth(lineWidth);
  int markerColor = 0; if(tags.getTagInteger("style."+key+".markerColor", markerColor) || tags.getTagInteger("style.markerColor", markerColor)) g->SetMarkerColor(markerColor);
  double markerSize = 0; if(tags.getTagDouble("style."+key+".markerSize", markerSize) || tags.getTagDouble("style.markerSize", markerSize)) g->SetMarkerSize(markerSize);
  int markerStyle = 0; if(tags.getTagInteger("style."+key+".markerStyle", markerStyle) || tags.getTagInteger("style.markerStyle", markerStyle)) g->SetMarkerStyle(markerStyle);
  if(tags.getTagBoolDefault ("style.binticks",false )){
    g->GetXaxis()->SetNdivisions(g->GetHistogram()->GetNbinsX(),0,0,false);
  }
}

//__________________________________________________________________________________|___________

void TQPlotter::setAxisLabels(TQTaggable& tags){
  // set the labels of the master histogram according to the avialable tags

  TH1* hMaster = this->getObject<TH1>("Graph_master");
  // @tags: labels.axes.mainX: control the x axis labels of the main frame
  TString xLabel = tags.getTagStringDefault("labels.axes.mainX", hMaster->GetXaxis()->GetTitle());
  hMaster->GetXaxis()->SetTitle(xLabel);

  if(TQHistogramUtils::getDimension(hMaster) == 1){
    TString xUnit = TQStringUtils::getUnit(TString(hMaster->GetXaxis()->GetTitle()));
    double binWidth = (hMaster->GetBinLowEdge(hMaster->GetNbinsX() + 1) -
                       hMaster->GetBinLowEdge(1)) / hMaster->GetNbinsX();

    // We're using variable width binning (should still work with fixed width)
    int densityBin = 0;
    if (tags.getTagInteger("scaleDensityToBin",densityBin)){
      binWidth = hMaster->GetXaxis()->GetBinWidth(densityBin);
    }

    bool isInteger = ((binWidth - (int)binWidth) < 0.0001);


    bool normalize = tags.getTagBoolDefault("normalize",false );

    TString yLabel = "Events";

    if(normalize){
      // "Events" or "arbitrary units"?
      yLabel = "arbitrary units";
    } else if (TQHistogramUtils::hasUniformBinning(hMaster) && !(xUnit.IsNull() && TMath::AreEqualRel(binWidth, 1., 1E-6))) {
      // there is only one case in which we don't have to add anything to the "Events" label: no unit on the x axis and a bin width of exactly 1
      // also, if the binning is irregular, we skip the bin width addition

      if (isInteger)
        yLabel.Append(TString::Format(" / %.0f", binWidth));
      else
        yLabel.Append(TString::Format(" / %.2g", binWidth));
      // append the unit of the x axis
      if (xUnit.Length() > 0)
        yLabel.Append(TString::Format(" %s", xUnit.Data()));
    }
    // @tags: labels.axes.mainY: control the y axis labels of the main frame (usually 'Events' or 'arbitrary units')
    tags.getTagString("labels.axes.mainY", yLabel);

    hMaster->GetYaxis()->SetTitle(yLabel.Data());
  } else {
    // for a >1D case, we just set whatever the user requested
    TString yLabel;
    if(tags.getTagString("labels.axes.mainY",yLabel)) hMaster->GetYaxis()->SetTitle(yLabel);
  }
}

//__________________________________________________________________________________|___________

TString TQPlotter::createAxisTagsAsString(const TString& prefix, const TString& title, double xCoeff, double yCoeff, double constCoeff, double wMin, double wMax, double xCoord, double yCoord, int /*nDiv*/){
  // convert a variable definition into tags for an additional axis
  TQTaggable tags;
  if(TQPlotter::createAxisTags(tags,prefix,title,xCoeff, yCoeff, constCoeff, wMin, wMax, xCoord, yCoord)){
    return tags.exportTagsAsString();
  }
  return "";
}

//__________________________________________________________________________________|___________

TString TQPlotter::createAxisTagsAsConfigString(const TString& prefix, const TString& title, double xCoeff, double yCoeff, double constCoeff, double wMin, double wMax, double xCoord, double yCoord, int /*nDiv*/){
  // convert a variable definition into tags for an additional axis
  TQTaggable tags;
  if(TQPlotter::createAxisTags(tags,prefix,title,xCoeff, yCoeff, constCoeff, wMin, wMax, xCoord, yCoord)){
    return tags.exportTagsAsConfigString("");
  }
  return "";
}

//__________________________________________________________________________________|___________

TQTaggable* TQPlotter::createAxisTags(const TString& prefix, const TString& title, double xCoeff, double yCoeff, double constCoeff, double wMin, double wMax, double xCoord, double yCoord, int /*nDiv*/){
  // convert a variable definition into tags for an additional axis
  TQTaggable* tags = new TQTaggable();;
  TQPlotter::createAxisTags(*tags,prefix,title,xCoeff, yCoeff, constCoeff, wMin, wMax, xCoord, yCoord);
  return tags;
}

//__________________________________________________________________________________|___________

bool TQPlotter::createAxisTags(TQTaggable& tags, const TString& prefix, const TString& title, double xCoeff, double yCoeff, double constCoeff, double wMin, double wMax, double xCoord, double yCoord, int nDiv){
  // convert a variable definition into tags for an additional axis
  double wCoord = xCoeff*xCoord + yCoeff*yCoord + constCoeff;
  double coeff2 = xCoeff* xCoeff + yCoeff * yCoeff;

  double tmin = (wMin - wCoord)/coeff2;
  double tmax = (wMax - wCoord)/coeff2;

  double xmin = xCoord + xCoeff * tmin;
  double xmax = xCoord + xCoeff * tmax;
  double ymin = yCoord + yCoeff * tmin;
  double ymax = yCoord + yCoeff * tmax;

  tags.setTagBool(prefix+"show",true);
  tags.setTagDouble(prefix+"xMin",xmin);
  tags.setTagDouble(prefix+"xMax",xmax);
  tags.setTagDouble(prefix+"yMin",ymin);
  tags.setTagDouble(prefix+"yMax",ymax);
  tags.setTagDouble(prefix+"wMin",wMin);
  tags.setTagDouble(prefix+"wMax",wMax);
  tags.setTagInteger(prefix+"nDiv",nDiv);
  tags.setTagString(prefix+"title",title);

  return true;
}

//__________________________________________________________________________________|___________

int TQPlotter::getNProcesses(const TString& tagFilter){
  // return the number of added processes matching the tag filter
  TQTaggableIterator itr(this->fProcesses);
  int retval = 0;
  while(itr.hasNext()){
    TQNamedTaggable* tags = itr.readNext();
    if(!tags) continue;
    if(tags->getTagBoolDefault(tagFilter,false)) retval++;
  }
  return retval;
}

//__________________________________________________________________________________|___________

int TQPlotter::sanitizeProcesses() {
  // sanitize all processes
  TQTaggableIterator itr(fProcesses);
  std::vector<TQNamedTaggable*> removals;
  int retval = 0;
  while(itr.hasNext()){
    TQNamedTaggable* process = itr.readNext();
    if(!process) continue;
    if(process->getTagStringDefault(".path","").Contains("|")){
      removals.push_back(process);
    }
  }
  for(size_t i=0; i<removals.size(); i++){
    fProcesses->Remove(removals[i]);
    delete removals[i];
    retval++;
  }
  return retval;
}

//__________________________________________________________________________________|___________

void TQPlotter::applyBlinding(TQTaggable& tags, TCollection* histosSig, TCollection* histosBkg, TCollection* histosData) {
  //determine total background and total signal to apply dynamic blinding criteria
  // note that this function modifies the data histograms in-place, i.e., you must pass in a TCollection of the data histograms to be (potentially) blinded. No internal lists of histos are updated/changed in this function!
  if (tags.hasMatchingTag("blind*")) {
    TH1 *totalBkg = TQHistogramUtils::sumHistograms(histosBkg);
    TH1 *totalSig = nullptr;
    // @tag: [blinding.sumSignals]: if set to true (default), all signal samples are summed. If false, only the largest signal in each bin is considered for the blinding.
    if (tags.getTagBoolDefault("blinding.sumSignals", true)) {
      DEBUGclass("blinding by the sum of all signal models");
      totalSig = TQHistogramUtils::sumHistograms(histosSig);
    } else {
      totalSig = TQHistogramUtils::createEnvelopingHistogram(histosSig);
      DEBUGclass("blind by the largest signal model");
    }
    bool fullBlind = false;
    if (!totalBkg || !totalSig) {
      WARNclass("Could not determine total signal and/or total background. Will fully blind data in this plot to be safe!");
      fullBlind = true;
    }
    if (!TQHistogramUtils::checkConsistency(totalBkg, totalSig)) {
      WARNclass("Total signal and total background histograms are inconsistent. Will fully blind data in this plot to be safe! (likely the plot will fail completely anyways)");
      fullBlind = true;
    }
    if (histosData) { //if there are not data histos just skip this part...
      double sOverBthreshold = 0.05;
      double sOverSqrtSpBthreshold = 0.125; //some more or less sensible default values
      //@tag: [blinding.SoverB, blinding.SoverSqrtSpB] if at least one of these tags is set data histograms are blinded in bins where the expected signal to background ratio or significance (s/sqrt(s+b)) exceed the configured values. For safety both criteria are applied with thresholds of 0.1 and 0.5 respectively if an option matching "blind*" is found (to avoid accidential unblinding by mistyping). If a bin is blinded the bin contents and error are set to zero. 
      bool useSoB = tags.getTagDouble("blinding.SoverB", sOverBthreshold);
      bool useSoSqrtSpB = tags.getTagDouble("blinding.SoverSqrtSpB", sOverSqrtSpBthreshold);
      if (! (useSoB || useSoSqrtSpB) ) { //if none of the criteria is selected there may be a user error (e.g. mis-spelled tag) so enable both with the defaults specified above
        WARNclass("It seems you requested data to be dynamically blinded but no thresholds for any supported criterion were found. Will use defaults for s/b (0.1) and s/sqrt(s+b) (0.5). The supported tag names are \"(plotter.)blinding.SoverB\" and \"(plotter.)blinding.SoverSqrtSpB\".");
        useSoB = true;
        useSoSqrtSpB = true;
      }
      TQTH1Iterator dataItr(histosData);
      while (dataItr.hasNext()) {
        TH1* dataHist = dataItr.readNext();
        if (!dataHist) continue;
        if (fullBlind || !TQHistogramUtils::checkConsistency(totalBkg,dataHist)) { //if something is odd, blind the entire data histogram
          for (int bin=0; bin<TQHistogramUtils::getNBins(dataHist); ++bin) {
            dataHist->SetBinContent(bin, 0.); dataHist->SetBinError(bin, 0.);
          }
        }
        double s=0,b=0;
        for (int bin=0; bin<TQHistogramUtils::getNBins(dataHist); ++bin) { //we can iterate over any histogram's nBins since they are verified to be consistent!
          s = totalSig->GetBinContent(bin);
          b = totalBkg->GetBinContent(bin);
          if (b==0 ||
              ( useSoB && s/b>sOverBthreshold ) ||
              ( useSoSqrtSpB && s*s/(s+b) > sOverSqrtSpBthreshold*sOverSqrtSpBthreshold )) {
            dataHist->SetBinContent(bin, 0.); dataHist->SetBinError(bin, 0.);
          }
        }
      }
    }
  }
  
}

//__________________________________________________________________________________|___________

TObjArray* TQPlotter::collectHistograms(TQTaggable& tags){
  // use the TQSampleDataReader to retrieve all histograms from the sample folder
  bool verbose = tags.getTagBoolDefault("verbose",false );

  //@tag: [style.showUnderflow,style.showOverflow] This argument tag controls if under/overflow bins are shown in the histogram. Default: false.
  bool showUnderflow = tags.getTagBoolDefault ("style.showUnderflow",false);
  bool showOverflow = tags.getTagBoolDefault ("style.showOverflow",false );
  tags.setTagBool("includeOverflow",showOverflow);
  tags.setTagBool("includeUnderflow",showUnderflow);

  //import alias and input tags
  TQTaggable aliases;
  aliases.importTagsWithoutPrefix(tags,"alias.");
  aliases.importTagsWithoutPrefix(tags,"input.");

  if(verbose) VERBOSEclass("getting data histograms");
  TObjArray* histosData = getHistograms(this->fProcesses,".isData", tags.getTagStringDefault("input.data", tags.getTagStringDefault("input.histogram","")), "", aliases, tags);
  if(verbose) VERBOSEclass("getting background histograms");
  TObjArray* histosBkg = getHistograms(this->fProcesses,".isBackground", tags.getTagStringDefault("input.bkg", tags.getTagStringDefault("input.histogram","")), "", aliases, tags);
  if(verbose) VERBOSEclass("getting signal histograms");
  TObjArray* histosSig = getHistograms(this->fProcesses,".isSignal", tags.getTagStringDefault("input.sig", tags.getTagStringDefault("input.histogram","")), "", aliases, tags);

  TObjArray* histos = new TObjArray();

  histos->AddAll(histosData);
  histos->AddAll(histosBkg);
  histos->AddAll(histosSig);
  if(histos->GetEntries() < 1){
    delete histos;
    ERRORclass("no histograms found: "+tags.exportTagsAsString("input.*"));
    return NULL;
  }

  if(!histosData || histosData->GetEntries() < 1){
    if(verbose) VERBOSEclass("no data histograms found, disabling data");
    tags.setTagBool("style.drawData",false);
  }
  if(!histosBkg || histosBkg->GetEntries() < 1){
    if(verbose) VERBOSEclass("no background histograms found, disabling background");
    tags.setTagBool("style.drawBkg",false);
  }
  if(!histosSig || histosSig->GetEntries() < 1){
    if(verbose) VERBOSEclass("no signal histograms found, disabling signal");
    tags.setTagBool("style.drawSig",false);
  }
  
  this->applyBlinding(tags,histosSig,histosBkg,histosData);
  
  // the histograms in these TObjArrays were already collected in "histos". 
  // The deletion of the individual lists is postponed up to this point to allow
  // for the checks and blinding logic in between.
  if(histosData) delete histosData;
  if(histosBkg) delete histosBkg;
  if(histosSig) delete histosSig;
  
  
  TQTH1Iterator itr(histos);
  //@tag: [requireMinimumContent] Skip histograms with integral below given value. This is set to 1e-5 by default!
  double minContent = tags.getTagDoubleDefault("requireMinimumContent",1e-5);
  double maxint = 0;
  while(itr.hasNext()){
    TH1* hist = itr.readNext();
    double integral = hist->Integral();
    DEBUGclass("%s has integral %g",hist->GetName(),integral);
    maxint = std::max(integral,maxint);
  }
  if(verbose) VERBOSEclass("highest integral of histogram set is %g",maxint);
  if( maxint < minContent){
    WARNclass("skipping plot '%s', histograms do not exceed minimum integral requirement (requireMinimumContent=%g)",tags.getTagStringDefault(".saveAs","?").Data(),minContent);
    delete histos;
    return NULL;
  }

  // check the consistency and create master histogram
  if(verbose) VERBOSEclass("checking histogram consistency");
  // expect at least one histogram to be available
  bool consistent = (histos->GetEntries() > 0);
  TH1* hMaster = NULL;
  consistent = checkConsistency(hMaster, histos) && consistent;
  if(!hMaster){
    if(verbose) VERBOSEclass("unable to obtain master histogram from consistency check!");
  }

  // stop if there is no valid histogram or histograms are invalid
  if (!consistent){
    if(verbose) VERBOSEclass("consistency check failed");
    delete histos;
    return NULL;
  }
  hMaster->Reset();
  this->addObject(histos,"histos");

  return histos;
}

//__________________________________________________________________________________|___________

void TQPlotter::drawLabels(TQTaggable& /*tags*/){
  // draw the labels given by the tags
  // does nothing by default, can be overridden by derived classes
}

//__________________________________________________________________________________|___________

TGraphAsymmErrors* TQPlotter::getRatioErrorGraph(TH1* hTotalStack){
  // get a TGraphAsymmErrors with the relative errors of a histogram
  int nBins = hTotalStack->GetNbinsX();

  int nPoints = 0;
  for (int i = 1; i <= nBins; i++) {
    if (hTotalStack->GetBinContent(i) != 0.) {
      nPoints++;
    }
  }

  TGraphAsymmErrors * ratioErrorGraph = new TGraphAsymmErrors(nPoints);
  ratioErrorGraph->SetName(TString::Format("ratioError%s",hTotalStack->GetName()));
  ratioErrorGraph->SetTitle("Monte Carlo ratio error band");

  int iPoint = 0;
  for (int iBin = 1; iBin <= nBins; iBin++) {
    double MC = hTotalStack->GetBinContent(iBin);
    double MCErr = hTotalStack->GetBinError(iBin);
    double MCErrUpper = MCErr;
    double MCErrLower = MCErr;
    if(MCErrUpper == 0 || MCErrLower == 0 || MC == 0) continue;
    double ratioBandErrorUpper =  MCErrUpper / MC;
    double ratioBandErrorLower =  MCErrLower / MC;
    // set the position and the width of the ratio error band
    ratioErrorGraph->SetPoint(iPoint, hTotalStack->GetBinCenter(iBin), 1.);
    ratioErrorGraph->SetPointError(iPoint, hTotalStack->GetBinWidth(iBin) / 2.,
                                   hTotalStack->GetBinWidth(iBin) / 2.,
                                   ratioBandErrorLower, ratioBandErrorUpper);
    iPoint++;
  }
  return ratioErrorGraph;
}

//__________________________________________________________________________________|___________

TGraphAsymmErrors* TQPlotter::getRatioGraph(TH1* h_data, TH1* hTotalBkg, bool invert, double ratioContentThreshold, bool verbose){
  // produce a TGraphAsymmErrors as the ratio between a data and an MC histogram

  int nBins = hTotalBkg->GetNbinsX();

  int nRatioPoints = 0;
  for (int i = 1; i <= nBins; i++) {
    double mcVal = hTotalBkg->GetBinContent(i);
    double dataVal = h_data->GetBinContent(i);
    if (mcVal < ratioContentThreshold || dataVal < ratioContentThreshold) continue;
    if(!TQUtils::isNum(mcVal)){
      WARNclass("encountered non-numeric MC value: %f",mcVal);
      continue;
    }
    if(!TQUtils::isNum(dataVal)){
      WARNclass("encountered non-numeric data value: %f",dataVal);
      continue;
    }
    nRatioPoints++;
  }

  if(nRatioPoints < 1){
    // there is nothing to draw -- well, let's do nothing, then
    return NULL;
  }

  // the graph used to draw the ratio points
  TGraphAsymmErrors * ratioGraph = new TGraphAsymmErrors(nRatioPoints);
  ratioGraph->SetName(TString::Format("ratio_%s_%s",h_data->GetName(),hTotalBkg->GetName()));
  ratioGraph->SetTitle(TString::Format("%s (ratio)",h_data->GetTitle()));
  ratioGraph->SetLineColor(h_data->GetLineColor());
  ratioGraph->SetMarkerSize(h_data->GetMarkerSize());
  ratioGraph->SetMarkerStyle(h_data->GetMarkerStyle());
  ratioGraph->SetMarkerColor(h_data->GetMarkerColor());

  int iRatioPoint = 0;

  // loop over all bins of the histogram
  for (int iBin = 1; iBin <= nBins; iBin++) {
    double x = hTotalBkg->GetBinCenter(iBin);
    // get the values and errors of data and MC for this bin
    double data    = h_data ->GetBinContent(iBin);
    double dataErrUp = h_data->GetBinErrorUp(iBin);
    double dataErrDown = h_data->GetBinErrorLow(iBin);
    double MC      = hTotalBkg->GetBinContent(iBin);
    // cannot do anything if MC expectation is zero
    if (MC < ratioContentThreshold || data < ratioContentThreshold) continue;

    double ratio = invert ? MC / data : data / MC;
    double ratioErrorUp = dataErrUp / MC;
    double ratioErrorDown = dataErrDown / MC;
    if(verbose) VERBOSEclass("adding ratio point with x=%f, y=%f (data=%f, MC=%f)",x,ratio,data,MC);
    ratioGraph->SetPoint(iRatioPoint, x, ratio);
    ratioGraph->SetPointError(iRatioPoint,
                              0,0,
                              ratioErrorDown,ratioErrorUp
                              );
    iRatioPoint++;
  }
  if(verbose) VERBOSEclass("completed ratio graph with %d (%d) points",iRatioPoint,ratioGraph->GetN());
  return ratioGraph;
}
 TQPlotter.cxx:1
 TQPlotter.cxx:2
 TQPlotter.cxx:3
 TQPlotter.cxx:4
 TQPlotter.cxx:5
 TQPlotter.cxx:6
 TQPlotter.cxx:7
 TQPlotter.cxx:8
 TQPlotter.cxx:9
 TQPlotter.cxx:10
 TQPlotter.cxx:11
 TQPlotter.cxx:12
 TQPlotter.cxx:13
 TQPlotter.cxx:14
 TQPlotter.cxx:15
 TQPlotter.cxx:16
 TQPlotter.cxx:17
 TQPlotter.cxx:18
 TQPlotter.cxx:19
 TQPlotter.cxx:20
 TQPlotter.cxx:21
 TQPlotter.cxx:22
 TQPlotter.cxx:23
 TQPlotter.cxx:24
 TQPlotter.cxx:25
 TQPlotter.cxx:26
 TQPlotter.cxx:27
 TQPlotter.cxx:28
 TQPlotter.cxx:29
 TQPlotter.cxx:30
 TQPlotter.cxx:31
 TQPlotter.cxx:32
 TQPlotter.cxx:33
 TQPlotter.cxx:34
 TQPlotter.cxx:35
 TQPlotter.cxx:36
 TQPlotter.cxx:37
 TQPlotter.cxx:38
 TQPlotter.cxx:39
 TQPlotter.cxx:40
 TQPlotter.cxx:41
 TQPlotter.cxx:42
 TQPlotter.cxx:43
 TQPlotter.cxx:44
 TQPlotter.cxx:45
 TQPlotter.cxx:46
 TQPlotter.cxx:47
 TQPlotter.cxx:48
 TQPlotter.cxx:49
 TQPlotter.cxx:50
 TQPlotter.cxx:51
 TQPlotter.cxx:52
 TQPlotter.cxx:53
 TQPlotter.cxx:54
 TQPlotter.cxx:55
 TQPlotter.cxx:56
 TQPlotter.cxx:57
 TQPlotter.cxx:58
 TQPlotter.cxx:59
 TQPlotter.cxx:60
 TQPlotter.cxx:61
 TQPlotter.cxx:62
 TQPlotter.cxx:63
 TQPlotter.cxx:64
 TQPlotter.cxx:65
 TQPlotter.cxx:66
 TQPlotter.cxx:67
 TQPlotter.cxx:68
 TQPlotter.cxx:69
 TQPlotter.cxx:70
 TQPlotter.cxx:71
 TQPlotter.cxx:72
 TQPlotter.cxx:73
 TQPlotter.cxx:74
 TQPlotter.cxx:75
 TQPlotter.cxx:76
 TQPlotter.cxx:77
 TQPlotter.cxx:78
 TQPlotter.cxx:79
 TQPlotter.cxx:80
 TQPlotter.cxx:81
 TQPlotter.cxx:82
 TQPlotter.cxx:83
 TQPlotter.cxx:84
 TQPlotter.cxx:85
 TQPlotter.cxx:86
 TQPlotter.cxx:87
 TQPlotter.cxx:88
 TQPlotter.cxx:89
 TQPlotter.cxx:90
 TQPlotter.cxx:91
 TQPlotter.cxx:92
 TQPlotter.cxx:93
 TQPlotter.cxx:94
 TQPlotter.cxx:95
 TQPlotter.cxx:96
 TQPlotter.cxx:97
 TQPlotter.cxx:98
 TQPlotter.cxx:99
 TQPlotter.cxx:100
 TQPlotter.cxx:101
 TQPlotter.cxx:102
 TQPlotter.cxx:103
 TQPlotter.cxx:104
 TQPlotter.cxx:105
 TQPlotter.cxx:106
 TQPlotter.cxx:107
 TQPlotter.cxx:108
 TQPlotter.cxx:109
 TQPlotter.cxx:110
 TQPlotter.cxx:111
 TQPlotter.cxx:112
 TQPlotter.cxx:113
 TQPlotter.cxx:114
 TQPlotter.cxx:115
 TQPlotter.cxx:116
 TQPlotter.cxx:117
 TQPlotter.cxx:118
 TQPlotter.cxx:119
 TQPlotter.cxx:120
 TQPlotter.cxx:121
 TQPlotter.cxx:122
 TQPlotter.cxx:123
 TQPlotter.cxx:124
 TQPlotter.cxx:125
 TQPlotter.cxx:126
 TQPlotter.cxx:127
 TQPlotter.cxx:128
 TQPlotter.cxx:129
 TQPlotter.cxx:130
 TQPlotter.cxx:131
 TQPlotter.cxx:132
 TQPlotter.cxx:133
 TQPlotter.cxx:134
 TQPlotter.cxx:135
 TQPlotter.cxx:136
 TQPlotter.cxx:137
 TQPlotter.cxx:138
 TQPlotter.cxx:139
 TQPlotter.cxx:140
 TQPlotter.cxx:141
 TQPlotter.cxx:142
 TQPlotter.cxx:143
 TQPlotter.cxx:144
 TQPlotter.cxx:145
 TQPlotter.cxx:146
 TQPlotter.cxx:147
 TQPlotter.cxx:148
 TQPlotter.cxx:149
 TQPlotter.cxx:150
 TQPlotter.cxx:151
 TQPlotter.cxx:152
 TQPlotter.cxx:153
 TQPlotter.cxx:154
 TQPlotter.cxx:155
 TQPlotter.cxx:156
 TQPlotter.cxx:157
 TQPlotter.cxx:158
 TQPlotter.cxx:159
 TQPlotter.cxx:160
 TQPlotter.cxx:161
 TQPlotter.cxx:162
 TQPlotter.cxx:163
 TQPlotter.cxx:164
 TQPlotter.cxx:165
 TQPlotter.cxx:166
 TQPlotter.cxx:167
 TQPlotter.cxx:168
 TQPlotter.cxx:169
 TQPlotter.cxx:170
 TQPlotter.cxx:171
 TQPlotter.cxx:172
 TQPlotter.cxx:173
 TQPlotter.cxx:174
 TQPlotter.cxx:175
 TQPlotter.cxx:176
 TQPlotter.cxx:177
 TQPlotter.cxx:178
 TQPlotter.cxx:179
 TQPlotter.cxx:180
 TQPlotter.cxx:181
 TQPlotter.cxx:182
 TQPlotter.cxx:183
 TQPlotter.cxx:184
 TQPlotter.cxx:185
 TQPlotter.cxx:186
 TQPlotter.cxx:187
 TQPlotter.cxx:188
 TQPlotter.cxx:189
 TQPlotter.cxx:190
 TQPlotter.cxx:191
 TQPlotter.cxx:192
 TQPlotter.cxx:193
 TQPlotter.cxx:194
 TQPlotter.cxx:195
 TQPlotter.cxx:196
 TQPlotter.cxx:197
 TQPlotter.cxx:198
 TQPlotter.cxx:199
 TQPlotter.cxx:200
 TQPlotter.cxx:201
 TQPlotter.cxx:202
 TQPlotter.cxx:203
 TQPlotter.cxx:204
 TQPlotter.cxx:205
 TQPlotter.cxx:206
 TQPlotter.cxx:207
 TQPlotter.cxx:208
 TQPlotter.cxx:209
 TQPlotter.cxx:210
 TQPlotter.cxx:211
 TQPlotter.cxx:212
 TQPlotter.cxx:213
 TQPlotter.cxx:214
 TQPlotter.cxx:215
 TQPlotter.cxx:216
 TQPlotter.cxx:217
 TQPlotter.cxx:218
 TQPlotter.cxx:219
 TQPlotter.cxx:220
 TQPlotter.cxx:221
 TQPlotter.cxx:222
 TQPlotter.cxx:223
 TQPlotter.cxx:224
 TQPlotter.cxx:225
 TQPlotter.cxx:226
 TQPlotter.cxx:227
 TQPlotter.cxx:228
 TQPlotter.cxx:229
 TQPlotter.cxx:230
 TQPlotter.cxx:231
 TQPlotter.cxx:232
 TQPlotter.cxx:233
 TQPlotter.cxx:234
 TQPlotter.cxx:235
 TQPlotter.cxx:236
 TQPlotter.cxx:237
 TQPlotter.cxx:238
 TQPlotter.cxx:239
 TQPlotter.cxx:240
 TQPlotter.cxx:241
 TQPlotter.cxx:242
 TQPlotter.cxx:243
 TQPlotter.cxx:244
 TQPlotter.cxx:245
 TQPlotter.cxx:246
 TQPlotter.cxx:247
 TQPlotter.cxx:248
 TQPlotter.cxx:249
 TQPlotter.cxx:250
 TQPlotter.cxx:251
 TQPlotter.cxx:252
 TQPlotter.cxx:253
 TQPlotter.cxx:254
 TQPlotter.cxx:255
 TQPlotter.cxx:256
 TQPlotter.cxx:257
 TQPlotter.cxx:258
 TQPlotter.cxx:259
 TQPlotter.cxx:260
 TQPlotter.cxx:261
 TQPlotter.cxx:262
 TQPlotter.cxx:263
 TQPlotter.cxx:264
 TQPlotter.cxx:265
 TQPlotter.cxx:266
 TQPlotter.cxx:267
 TQPlotter.cxx:268
 TQPlotter.cxx:269
 TQPlotter.cxx:270
 TQPlotter.cxx:271
 TQPlotter.cxx:272
 TQPlotter.cxx:273
 TQPlotter.cxx:274
 TQPlotter.cxx:275
 TQPlotter.cxx:276
 TQPlotter.cxx:277
 TQPlotter.cxx:278
 TQPlotter.cxx:279
 TQPlotter.cxx:280
 TQPlotter.cxx:281
 TQPlotter.cxx:282
 TQPlotter.cxx:283
 TQPlotter.cxx:284
 TQPlotter.cxx:285
 TQPlotter.cxx:286
 TQPlotter.cxx:287
 TQPlotter.cxx:288
 TQPlotter.cxx:289
 TQPlotter.cxx:290
 TQPlotter.cxx:291
 TQPlotter.cxx:292
 TQPlotter.cxx:293
 TQPlotter.cxx:294
 TQPlotter.cxx:295
 TQPlotter.cxx:296
 TQPlotter.cxx:297
 TQPlotter.cxx:298
 TQPlotter.cxx:299
 TQPlotter.cxx:300
 TQPlotter.cxx:301
 TQPlotter.cxx:302
 TQPlotter.cxx:303
 TQPlotter.cxx:304
 TQPlotter.cxx:305
 TQPlotter.cxx:306
 TQPlotter.cxx:307
 TQPlotter.cxx:308
 TQPlotter.cxx:309
 TQPlotter.cxx:310
 TQPlotter.cxx:311
 TQPlotter.cxx:312
 TQPlotter.cxx:313
 TQPlotter.cxx:314
 TQPlotter.cxx:315
 TQPlotter.cxx:316
 TQPlotter.cxx:317
 TQPlotter.cxx:318
 TQPlotter.cxx:319
 TQPlotter.cxx:320
 TQPlotter.cxx:321
 TQPlotter.cxx:322
 TQPlotter.cxx:323
 TQPlotter.cxx:324
 TQPlotter.cxx:325
 TQPlotter.cxx:326
 TQPlotter.cxx:327
 TQPlotter.cxx:328
 TQPlotter.cxx:329
 TQPlotter.cxx:330
 TQPlotter.cxx:331
 TQPlotter.cxx:332
 TQPlotter.cxx:333
 TQPlotter.cxx:334
 TQPlotter.cxx:335
 TQPlotter.cxx:336
 TQPlotter.cxx:337
 TQPlotter.cxx:338
 TQPlotter.cxx:339
 TQPlotter.cxx:340
 TQPlotter.cxx:341
 TQPlotter.cxx:342
 TQPlotter.cxx:343
 TQPlotter.cxx:344
 TQPlotter.cxx:345
 TQPlotter.cxx:346
 TQPlotter.cxx:347
 TQPlotter.cxx:348
 TQPlotter.cxx:349
 TQPlotter.cxx:350
 TQPlotter.cxx:351
 TQPlotter.cxx:352
 TQPlotter.cxx:353
 TQPlotter.cxx:354
 TQPlotter.cxx:355
 TQPlotter.cxx:356
 TQPlotter.cxx:357
 TQPlotter.cxx:358
 TQPlotter.cxx:359
 TQPlotter.cxx:360
 TQPlotter.cxx:361
 TQPlotter.cxx:362
 TQPlotter.cxx:363
 TQPlotter.cxx:364
 TQPlotter.cxx:365
 TQPlotter.cxx:366
 TQPlotter.cxx:367
 TQPlotter.cxx:368
 TQPlotter.cxx:369
 TQPlotter.cxx:370
 TQPlotter.cxx:371
 TQPlotter.cxx:372
 TQPlotter.cxx:373
 TQPlotter.cxx:374
 TQPlotter.cxx:375
 TQPlotter.cxx:376
 TQPlotter.cxx:377
 TQPlotter.cxx:378
 TQPlotter.cxx:379
 TQPlotter.cxx:380
 TQPlotter.cxx:381
 TQPlotter.cxx:382
 TQPlotter.cxx:383
 TQPlotter.cxx:384
 TQPlotter.cxx:385
 TQPlotter.cxx:386
 TQPlotter.cxx:387
 TQPlotter.cxx:388
 TQPlotter.cxx:389
 TQPlotter.cxx:390
 TQPlotter.cxx:391
 TQPlotter.cxx:392
 TQPlotter.cxx:393
 TQPlotter.cxx:394
 TQPlotter.cxx:395
 TQPlotter.cxx:396
 TQPlotter.cxx:397
 TQPlotter.cxx:398
 TQPlotter.cxx:399
 TQPlotter.cxx:400
 TQPlotter.cxx:401
 TQPlotter.cxx:402
 TQPlotter.cxx:403
 TQPlotter.cxx:404
 TQPlotter.cxx:405
 TQPlotter.cxx:406
 TQPlotter.cxx:407
 TQPlotter.cxx:408
 TQPlotter.cxx:409
 TQPlotter.cxx:410
 TQPlotter.cxx:411
 TQPlotter.cxx:412
 TQPlotter.cxx:413
 TQPlotter.cxx:414
 TQPlotter.cxx:415
 TQPlotter.cxx:416
 TQPlotter.cxx:417
 TQPlotter.cxx:418
 TQPlotter.cxx:419
 TQPlotter.cxx:420
 TQPlotter.cxx:421
 TQPlotter.cxx:422
 TQPlotter.cxx:423
 TQPlotter.cxx:424
 TQPlotter.cxx:425
 TQPlotter.cxx:426
 TQPlotter.cxx:427
 TQPlotter.cxx:428
 TQPlotter.cxx:429
 TQPlotter.cxx:430
 TQPlotter.cxx:431
 TQPlotter.cxx:432
 TQPlotter.cxx:433
 TQPlotter.cxx:434
 TQPlotter.cxx:435
 TQPlotter.cxx:436
 TQPlotter.cxx:437
 TQPlotter.cxx:438
 TQPlotter.cxx:439
 TQPlotter.cxx:440
 TQPlotter.cxx:441
 TQPlotter.cxx:442
 TQPlotter.cxx:443
 TQPlotter.cxx:444
 TQPlotter.cxx:445
 TQPlotter.cxx:446
 TQPlotter.cxx:447
 TQPlotter.cxx:448
 TQPlotter.cxx:449
 TQPlotter.cxx:450
 TQPlotter.cxx:451
 TQPlotter.cxx:452
 TQPlotter.cxx:453
 TQPlotter.cxx:454
 TQPlotter.cxx:455
 TQPlotter.cxx:456
 TQPlotter.cxx:457
 TQPlotter.cxx:458
 TQPlotter.cxx:459
 TQPlotter.cxx:460
 TQPlotter.cxx:461
 TQPlotter.cxx:462
 TQPlotter.cxx:463
 TQPlotter.cxx:464
 TQPlotter.cxx:465
 TQPlotter.cxx:466
 TQPlotter.cxx:467
 TQPlotter.cxx:468
 TQPlotter.cxx:469
 TQPlotter.cxx:470
 TQPlotter.cxx:471
 TQPlotter.cxx:472
 TQPlotter.cxx:473
 TQPlotter.cxx:474
 TQPlotter.cxx:475
 TQPlotter.cxx:476
 TQPlotter.cxx:477
 TQPlotter.cxx:478
 TQPlotter.cxx:479
 TQPlotter.cxx:480
 TQPlotter.cxx:481
 TQPlotter.cxx:482
 TQPlotter.cxx:483
 TQPlotter.cxx:484
 TQPlotter.cxx:485
 TQPlotter.cxx:486
 TQPlotter.cxx:487
 TQPlotter.cxx:488
 TQPlotter.cxx:489
 TQPlotter.cxx:490
 TQPlotter.cxx:491
 TQPlotter.cxx:492
 TQPlotter.cxx:493
 TQPlotter.cxx:494
 TQPlotter.cxx:495
 TQPlotter.cxx:496
 TQPlotter.cxx:497
 TQPlotter.cxx:498
 TQPlotter.cxx:499
 TQPlotter.cxx:500
 TQPlotter.cxx:501
 TQPlotter.cxx:502
 TQPlotter.cxx:503
 TQPlotter.cxx:504
 TQPlotter.cxx:505
 TQPlotter.cxx:506
 TQPlotter.cxx:507
 TQPlotter.cxx:508
 TQPlotter.cxx:509
 TQPlotter.cxx:510
 TQPlotter.cxx:511
 TQPlotter.cxx:512
 TQPlotter.cxx:513
 TQPlotter.cxx:514
 TQPlotter.cxx:515
 TQPlotter.cxx:516
 TQPlotter.cxx:517
 TQPlotter.cxx:518
 TQPlotter.cxx:519
 TQPlotter.cxx:520
 TQPlotter.cxx:521
 TQPlotter.cxx:522
 TQPlotter.cxx:523
 TQPlotter.cxx:524
 TQPlotter.cxx:525
 TQPlotter.cxx:526
 TQPlotter.cxx:527
 TQPlotter.cxx:528
 TQPlotter.cxx:529
 TQPlotter.cxx:530
 TQPlotter.cxx:531
 TQPlotter.cxx:532
 TQPlotter.cxx:533
 TQPlotter.cxx:534
 TQPlotter.cxx:535
 TQPlotter.cxx:536
 TQPlotter.cxx:537
 TQPlotter.cxx:538
 TQPlotter.cxx:539
 TQPlotter.cxx:540
 TQPlotter.cxx:541
 TQPlotter.cxx:542
 TQPlotter.cxx:543
 TQPlotter.cxx:544
 TQPlotter.cxx:545
 TQPlotter.cxx:546
 TQPlotter.cxx:547
 TQPlotter.cxx:548
 TQPlotter.cxx:549
 TQPlotter.cxx:550
 TQPlotter.cxx:551
 TQPlotter.cxx:552
 TQPlotter.cxx:553
 TQPlotter.cxx:554
 TQPlotter.cxx:555
 TQPlotter.cxx:556
 TQPlotter.cxx:557
 TQPlotter.cxx:558
 TQPlotter.cxx:559
 TQPlotter.cxx:560
 TQPlotter.cxx:561
 TQPlotter.cxx:562
 TQPlotter.cxx:563
 TQPlotter.cxx:564
 TQPlotter.cxx:565
 TQPlotter.cxx:566
 TQPlotter.cxx:567
 TQPlotter.cxx:568
 TQPlotter.cxx:569
 TQPlotter.cxx:570
 TQPlotter.cxx:571
 TQPlotter.cxx:572
 TQPlotter.cxx:573
 TQPlotter.cxx:574
 TQPlotter.cxx:575
 TQPlotter.cxx:576
 TQPlotter.cxx:577
 TQPlotter.cxx:578
 TQPlotter.cxx:579
 TQPlotter.cxx:580
 TQPlotter.cxx:581
 TQPlotter.cxx:582
 TQPlotter.cxx:583
 TQPlotter.cxx:584
 TQPlotter.cxx:585
 TQPlotter.cxx:586
 TQPlotter.cxx:587
 TQPlotter.cxx:588
 TQPlotter.cxx:589
 TQPlotter.cxx:590
 TQPlotter.cxx:591
 TQPlotter.cxx:592
 TQPlotter.cxx:593
 TQPlotter.cxx:594
 TQPlotter.cxx:595
 TQPlotter.cxx:596
 TQPlotter.cxx:597
 TQPlotter.cxx:598
 TQPlotter.cxx:599
 TQPlotter.cxx:600
 TQPlotter.cxx:601
 TQPlotter.cxx:602
 TQPlotter.cxx:603
 TQPlotter.cxx:604
 TQPlotter.cxx:605
 TQPlotter.cxx:606
 TQPlotter.cxx:607
 TQPlotter.cxx:608
 TQPlotter.cxx:609
 TQPlotter.cxx:610
 TQPlotter.cxx:611
 TQPlotter.cxx:612
 TQPlotter.cxx:613
 TQPlotter.cxx:614
 TQPlotter.cxx:615
 TQPlotter.cxx:616
 TQPlotter.cxx:617
 TQPlotter.cxx:618
 TQPlotter.cxx:619
 TQPlotter.cxx:620
 TQPlotter.cxx:621
 TQPlotter.cxx:622
 TQPlotter.cxx:623
 TQPlotter.cxx:624
 TQPlotter.cxx:625
 TQPlotter.cxx:626
 TQPlotter.cxx:627
 TQPlotter.cxx:628
 TQPlotter.cxx:629
 TQPlotter.cxx:630
 TQPlotter.cxx:631
 TQPlotter.cxx:632
 TQPlotter.cxx:633
 TQPlotter.cxx:634
 TQPlotter.cxx:635
 TQPlotter.cxx:636
 TQPlotter.cxx:637
 TQPlotter.cxx:638
 TQPlotter.cxx:639
 TQPlotter.cxx:640
 TQPlotter.cxx:641
 TQPlotter.cxx:642
 TQPlotter.cxx:643
 TQPlotter.cxx:644
 TQPlotter.cxx:645
 TQPlotter.cxx:646
 TQPlotter.cxx:647
 TQPlotter.cxx:648
 TQPlotter.cxx:649
 TQPlotter.cxx:650
 TQPlotter.cxx:651
 TQPlotter.cxx:652
 TQPlotter.cxx:653
 TQPlotter.cxx:654
 TQPlotter.cxx:655
 TQPlotter.cxx:656
 TQPlotter.cxx:657
 TQPlotter.cxx:658
 TQPlotter.cxx:659
 TQPlotter.cxx:660
 TQPlotter.cxx:661
 TQPlotter.cxx:662
 TQPlotter.cxx:663
 TQPlotter.cxx:664
 TQPlotter.cxx:665
 TQPlotter.cxx:666
 TQPlotter.cxx:667
 TQPlotter.cxx:668
 TQPlotter.cxx:669
 TQPlotter.cxx:670
 TQPlotter.cxx:671
 TQPlotter.cxx:672
 TQPlotter.cxx:673
 TQPlotter.cxx:674
 TQPlotter.cxx:675
 TQPlotter.cxx:676
 TQPlotter.cxx:677
 TQPlotter.cxx:678
 TQPlotter.cxx:679
 TQPlotter.cxx:680
 TQPlotter.cxx:681
 TQPlotter.cxx:682
 TQPlotter.cxx:683
 TQPlotter.cxx:684
 TQPlotter.cxx:685
 TQPlotter.cxx:686
 TQPlotter.cxx:687
 TQPlotter.cxx:688
 TQPlotter.cxx:689
 TQPlotter.cxx:690
 TQPlotter.cxx:691
 TQPlotter.cxx:692
 TQPlotter.cxx:693
 TQPlotter.cxx:694
 TQPlotter.cxx:695
 TQPlotter.cxx:696
 TQPlotter.cxx:697
 TQPlotter.cxx:698
 TQPlotter.cxx:699
 TQPlotter.cxx:700
 TQPlotter.cxx:701
 TQPlotter.cxx:702
 TQPlotter.cxx:703
 TQPlotter.cxx:704
 TQPlotter.cxx:705
 TQPlotter.cxx:706
 TQPlotter.cxx:707
 TQPlotter.cxx:708
 TQPlotter.cxx:709
 TQPlotter.cxx:710
 TQPlotter.cxx:711
 TQPlotter.cxx:712
 TQPlotter.cxx:713
 TQPlotter.cxx:714
 TQPlotter.cxx:715
 TQPlotter.cxx:716
 TQPlotter.cxx:717
 TQPlotter.cxx:718
 TQPlotter.cxx:719
 TQPlotter.cxx:720
 TQPlotter.cxx:721
 TQPlotter.cxx:722
 TQPlotter.cxx:723
 TQPlotter.cxx:724
 TQPlotter.cxx:725
 TQPlotter.cxx:726
 TQPlotter.cxx:727
 TQPlotter.cxx:728
 TQPlotter.cxx:729
 TQPlotter.cxx:730
 TQPlotter.cxx:731
 TQPlotter.cxx:732
 TQPlotter.cxx:733
 TQPlotter.cxx:734
 TQPlotter.cxx:735
 TQPlotter.cxx:736
 TQPlotter.cxx:737
 TQPlotter.cxx:738
 TQPlotter.cxx:739
 TQPlotter.cxx:740
 TQPlotter.cxx:741
 TQPlotter.cxx:742
 TQPlotter.cxx:743
 TQPlotter.cxx:744
 TQPlotter.cxx:745
 TQPlotter.cxx:746
 TQPlotter.cxx:747
 TQPlotter.cxx:748
 TQPlotter.cxx:749
 TQPlotter.cxx:750
 TQPlotter.cxx:751
 TQPlotter.cxx:752
 TQPlotter.cxx:753
 TQPlotter.cxx:754
 TQPlotter.cxx:755
 TQPlotter.cxx:756
 TQPlotter.cxx:757
 TQPlotter.cxx:758
 TQPlotter.cxx:759
 TQPlotter.cxx:760
 TQPlotter.cxx:761
 TQPlotter.cxx:762
 TQPlotter.cxx:763
 TQPlotter.cxx:764
 TQPlotter.cxx:765
 TQPlotter.cxx:766
 TQPlotter.cxx:767
 TQPlotter.cxx:768
 TQPlotter.cxx:769
 TQPlotter.cxx:770
 TQPlotter.cxx:771
 TQPlotter.cxx:772
 TQPlotter.cxx:773
 TQPlotter.cxx:774
 TQPlotter.cxx:775
 TQPlotter.cxx:776
 TQPlotter.cxx:777
 TQPlotter.cxx:778
 TQPlotter.cxx:779
 TQPlotter.cxx:780
 TQPlotter.cxx:781
 TQPlotter.cxx:782
 TQPlotter.cxx:783
 TQPlotter.cxx:784
 TQPlotter.cxx:785
 TQPlotter.cxx:786
 TQPlotter.cxx:787
 TQPlotter.cxx:788
 TQPlotter.cxx:789
 TQPlotter.cxx:790
 TQPlotter.cxx:791
 TQPlotter.cxx:792
 TQPlotter.cxx:793
 TQPlotter.cxx:794
 TQPlotter.cxx:795
 TQPlotter.cxx:796
 TQPlotter.cxx:797
 TQPlotter.cxx:798
 TQPlotter.cxx:799
 TQPlotter.cxx:800
 TQPlotter.cxx:801
 TQPlotter.cxx:802
 TQPlotter.cxx:803
 TQPlotter.cxx:804
 TQPlotter.cxx:805
 TQPlotter.cxx:806
 TQPlotter.cxx:807
 TQPlotter.cxx:808
 TQPlotter.cxx:809
 TQPlotter.cxx:810
 TQPlotter.cxx:811
 TQPlotter.cxx:812
 TQPlotter.cxx:813
 TQPlotter.cxx:814
 TQPlotter.cxx:815
 TQPlotter.cxx:816
 TQPlotter.cxx:817
 TQPlotter.cxx:818
 TQPlotter.cxx:819
 TQPlotter.cxx:820
 TQPlotter.cxx:821
 TQPlotter.cxx:822
 TQPlotter.cxx:823
 TQPlotter.cxx:824
 TQPlotter.cxx:825
 TQPlotter.cxx:826
 TQPlotter.cxx:827
 TQPlotter.cxx:828
 TQPlotter.cxx:829
 TQPlotter.cxx:830
 TQPlotter.cxx:831
 TQPlotter.cxx:832
 TQPlotter.cxx:833
 TQPlotter.cxx:834
 TQPlotter.cxx:835
 TQPlotter.cxx:836
 TQPlotter.cxx:837
 TQPlotter.cxx:838
 TQPlotter.cxx:839
 TQPlotter.cxx:840
 TQPlotter.cxx:841
 TQPlotter.cxx:842
 TQPlotter.cxx:843
 TQPlotter.cxx:844
 TQPlotter.cxx:845
 TQPlotter.cxx:846
 TQPlotter.cxx:847
 TQPlotter.cxx:848
 TQPlotter.cxx:849
 TQPlotter.cxx:850
 TQPlotter.cxx:851
 TQPlotter.cxx:852
 TQPlotter.cxx:853
 TQPlotter.cxx:854
 TQPlotter.cxx:855
 TQPlotter.cxx:856
 TQPlotter.cxx:857
 TQPlotter.cxx:858
 TQPlotter.cxx:859
 TQPlotter.cxx:860
 TQPlotter.cxx:861
 TQPlotter.cxx:862
 TQPlotter.cxx:863
 TQPlotter.cxx:864
 TQPlotter.cxx:865
 TQPlotter.cxx:866
 TQPlotter.cxx:867
 TQPlotter.cxx:868
 TQPlotter.cxx:869
 TQPlotter.cxx:870
 TQPlotter.cxx:871
 TQPlotter.cxx:872
 TQPlotter.cxx:873
 TQPlotter.cxx:874
 TQPlotter.cxx:875
 TQPlotter.cxx:876
 TQPlotter.cxx:877
 TQPlotter.cxx:878
 TQPlotter.cxx:879
 TQPlotter.cxx:880
 TQPlotter.cxx:881
 TQPlotter.cxx:882
 TQPlotter.cxx:883
 TQPlotter.cxx:884
 TQPlotter.cxx:885
 TQPlotter.cxx:886
 TQPlotter.cxx:887
 TQPlotter.cxx:888
 TQPlotter.cxx:889
 TQPlotter.cxx:890
 TQPlotter.cxx:891
 TQPlotter.cxx:892
 TQPlotter.cxx:893
 TQPlotter.cxx:894
 TQPlotter.cxx:895
 TQPlotter.cxx:896
 TQPlotter.cxx:897
 TQPlotter.cxx:898
 TQPlotter.cxx:899
 TQPlotter.cxx:900
 TQPlotter.cxx:901
 TQPlotter.cxx:902
 TQPlotter.cxx:903
 TQPlotter.cxx:904
 TQPlotter.cxx:905
 TQPlotter.cxx:906
 TQPlotter.cxx:907
 TQPlotter.cxx:908
 TQPlotter.cxx:909
 TQPlotter.cxx:910
 TQPlotter.cxx:911
 TQPlotter.cxx:912
 TQPlotter.cxx:913
 TQPlotter.cxx:914
 TQPlotter.cxx:915
 TQPlotter.cxx:916
 TQPlotter.cxx:917
 TQPlotter.cxx:918
 TQPlotter.cxx:919
 TQPlotter.cxx:920
 TQPlotter.cxx:921
 TQPlotter.cxx:922
 TQPlotter.cxx:923
 TQPlotter.cxx:924
 TQPlotter.cxx:925
 TQPlotter.cxx:926
 TQPlotter.cxx:927
 TQPlotter.cxx:928
 TQPlotter.cxx:929
 TQPlotter.cxx:930
 TQPlotter.cxx:931
 TQPlotter.cxx:932
 TQPlotter.cxx:933
 TQPlotter.cxx:934
 TQPlotter.cxx:935
 TQPlotter.cxx:936
 TQPlotter.cxx:937
 TQPlotter.cxx:938
 TQPlotter.cxx:939
 TQPlotter.cxx:940
 TQPlotter.cxx:941
 TQPlotter.cxx:942
 TQPlotter.cxx:943
 TQPlotter.cxx:944
 TQPlotter.cxx:945
 TQPlotter.cxx:946
 TQPlotter.cxx:947
 TQPlotter.cxx:948
 TQPlotter.cxx:949
 TQPlotter.cxx:950
 TQPlotter.cxx:951
 TQPlotter.cxx:952
 TQPlotter.cxx:953
 TQPlotter.cxx:954
 TQPlotter.cxx:955
 TQPlotter.cxx:956
 TQPlotter.cxx:957
 TQPlotter.cxx:958
 TQPlotter.cxx:959
 TQPlotter.cxx:960
 TQPlotter.cxx:961
 TQPlotter.cxx:962
 TQPlotter.cxx:963
 TQPlotter.cxx:964
 TQPlotter.cxx:965
 TQPlotter.cxx:966
 TQPlotter.cxx:967
 TQPlotter.cxx:968
 TQPlotter.cxx:969
 TQPlotter.cxx:970
 TQPlotter.cxx:971
 TQPlotter.cxx:972
 TQPlotter.cxx:973
 TQPlotter.cxx:974
 TQPlotter.cxx:975
 TQPlotter.cxx:976
 TQPlotter.cxx:977
 TQPlotter.cxx:978
 TQPlotter.cxx:979
 TQPlotter.cxx:980
 TQPlotter.cxx:981
 TQPlotter.cxx:982
 TQPlotter.cxx:983
 TQPlotter.cxx:984
 TQPlotter.cxx:985
 TQPlotter.cxx:986
 TQPlotter.cxx:987
 TQPlotter.cxx:988
 TQPlotter.cxx:989
 TQPlotter.cxx:990
 TQPlotter.cxx:991
 TQPlotter.cxx:992
 TQPlotter.cxx:993
 TQPlotter.cxx:994
 TQPlotter.cxx:995
 TQPlotter.cxx:996
 TQPlotter.cxx:997
 TQPlotter.cxx:998
 TQPlotter.cxx:999
 TQPlotter.cxx:1000
 TQPlotter.cxx:1001
 TQPlotter.cxx:1002
 TQPlotter.cxx:1003
 TQPlotter.cxx:1004
 TQPlotter.cxx:1005
 TQPlotter.cxx:1006
 TQPlotter.cxx:1007
 TQPlotter.cxx:1008
 TQPlotter.cxx:1009
 TQPlotter.cxx:1010
 TQPlotter.cxx:1011
 TQPlotter.cxx:1012
 TQPlotter.cxx:1013
 TQPlotter.cxx:1014
 TQPlotter.cxx:1015
 TQPlotter.cxx:1016
 TQPlotter.cxx:1017
 TQPlotter.cxx:1018
 TQPlotter.cxx:1019
 TQPlotter.cxx:1020
 TQPlotter.cxx:1021
 TQPlotter.cxx:1022
 TQPlotter.cxx:1023
 TQPlotter.cxx:1024
 TQPlotter.cxx:1025
 TQPlotter.cxx:1026
 TQPlotter.cxx:1027
 TQPlotter.cxx:1028
 TQPlotter.cxx:1029
 TQPlotter.cxx:1030
 TQPlotter.cxx:1031
 TQPlotter.cxx:1032
 TQPlotter.cxx:1033
 TQPlotter.cxx:1034
 TQPlotter.cxx:1035
 TQPlotter.cxx:1036
 TQPlotter.cxx:1037
 TQPlotter.cxx:1038
 TQPlotter.cxx:1039
 TQPlotter.cxx:1040
 TQPlotter.cxx:1041
 TQPlotter.cxx:1042
 TQPlotter.cxx:1043
 TQPlotter.cxx:1044
 TQPlotter.cxx:1045
 TQPlotter.cxx:1046
 TQPlotter.cxx:1047
 TQPlotter.cxx:1048
 TQPlotter.cxx:1049
 TQPlotter.cxx:1050
 TQPlotter.cxx:1051
 TQPlotter.cxx:1052
 TQPlotter.cxx:1053
 TQPlotter.cxx:1054
 TQPlotter.cxx:1055
 TQPlotter.cxx:1056
 TQPlotter.cxx:1057
 TQPlotter.cxx:1058
 TQPlotter.cxx:1059
 TQPlotter.cxx:1060
 TQPlotter.cxx:1061
 TQPlotter.cxx:1062
 TQPlotter.cxx:1063
 TQPlotter.cxx:1064
 TQPlotter.cxx:1065
 TQPlotter.cxx:1066
 TQPlotter.cxx:1067
 TQPlotter.cxx:1068
 TQPlotter.cxx:1069
 TQPlotter.cxx:1070
 TQPlotter.cxx:1071
 TQPlotter.cxx:1072
 TQPlotter.cxx:1073
 TQPlotter.cxx:1074
 TQPlotter.cxx:1075
 TQPlotter.cxx:1076
 TQPlotter.cxx:1077
 TQPlotter.cxx:1078
 TQPlotter.cxx:1079
 TQPlotter.cxx:1080
 TQPlotter.cxx:1081
 TQPlotter.cxx:1082
 TQPlotter.cxx:1083
 TQPlotter.cxx:1084
 TQPlotter.cxx:1085
 TQPlotter.cxx:1086
 TQPlotter.cxx:1087
 TQPlotter.cxx:1088
 TQPlotter.cxx:1089
 TQPlotter.cxx:1090
 TQPlotter.cxx:1091
 TQPlotter.cxx:1092
 TQPlotter.cxx:1093
 TQPlotter.cxx:1094
 TQPlotter.cxx:1095
 TQPlotter.cxx:1096
 TQPlotter.cxx:1097
 TQPlotter.cxx:1098
 TQPlotter.cxx:1099
 TQPlotter.cxx:1100
 TQPlotter.cxx:1101
 TQPlotter.cxx:1102
 TQPlotter.cxx:1103
 TQPlotter.cxx:1104
 TQPlotter.cxx:1105
 TQPlotter.cxx:1106
 TQPlotter.cxx:1107
 TQPlotter.cxx:1108
 TQPlotter.cxx:1109
 TQPlotter.cxx:1110
 TQPlotter.cxx:1111
 TQPlotter.cxx:1112
 TQPlotter.cxx:1113
 TQPlotter.cxx:1114
 TQPlotter.cxx:1115
 TQPlotter.cxx:1116
 TQPlotter.cxx:1117
 TQPlotter.cxx:1118
 TQPlotter.cxx:1119
 TQPlotter.cxx:1120
 TQPlotter.cxx:1121
 TQPlotter.cxx:1122
 TQPlotter.cxx:1123
 TQPlotter.cxx:1124
 TQPlotter.cxx:1125
 TQPlotter.cxx:1126
 TQPlotter.cxx:1127
 TQPlotter.cxx:1128
 TQPlotter.cxx:1129
 TQPlotter.cxx:1130
 TQPlotter.cxx:1131
 TQPlotter.cxx:1132
 TQPlotter.cxx:1133
 TQPlotter.cxx:1134
 TQPlotter.cxx:1135
 TQPlotter.cxx:1136
 TQPlotter.cxx:1137
 TQPlotter.cxx:1138
 TQPlotter.cxx:1139
 TQPlotter.cxx:1140
 TQPlotter.cxx:1141
 TQPlotter.cxx:1142
 TQPlotter.cxx:1143
 TQPlotter.cxx:1144
 TQPlotter.cxx:1145
 TQPlotter.cxx:1146
 TQPlotter.cxx:1147
 TQPlotter.cxx:1148
 TQPlotter.cxx:1149
 TQPlotter.cxx:1150
 TQPlotter.cxx:1151
 TQPlotter.cxx:1152
 TQPlotter.cxx:1153
 TQPlotter.cxx:1154
 TQPlotter.cxx:1155
 TQPlotter.cxx:1156
 TQPlotter.cxx:1157
 TQPlotter.cxx:1158
 TQPlotter.cxx:1159
 TQPlotter.cxx:1160
 TQPlotter.cxx:1161
 TQPlotter.cxx:1162
 TQPlotter.cxx:1163
 TQPlotter.cxx:1164
 TQPlotter.cxx:1165
 TQPlotter.cxx:1166
 TQPlotter.cxx:1167
 TQPlotter.cxx:1168
 TQPlotter.cxx:1169
 TQPlotter.cxx:1170
 TQPlotter.cxx:1171
 TQPlotter.cxx:1172
 TQPlotter.cxx:1173
 TQPlotter.cxx:1174
 TQPlotter.cxx:1175
 TQPlotter.cxx:1176
 TQPlotter.cxx:1177
 TQPlotter.cxx:1178
 TQPlotter.cxx:1179
 TQPlotter.cxx:1180
 TQPlotter.cxx:1181
 TQPlotter.cxx:1182
 TQPlotter.cxx:1183
 TQPlotter.cxx:1184
 TQPlotter.cxx:1185
 TQPlotter.cxx:1186
 TQPlotter.cxx:1187
 TQPlotter.cxx:1188
 TQPlotter.cxx:1189
 TQPlotter.cxx:1190
 TQPlotter.cxx:1191
 TQPlotter.cxx:1192
 TQPlotter.cxx:1193
 TQPlotter.cxx:1194
 TQPlotter.cxx:1195
 TQPlotter.cxx:1196
 TQPlotter.cxx:1197
 TQPlotter.cxx:1198
 TQPlotter.cxx:1199
 TQPlotter.cxx:1200
 TQPlotter.cxx:1201
 TQPlotter.cxx:1202
 TQPlotter.cxx:1203
 TQPlotter.cxx:1204
 TQPlotter.cxx:1205
 TQPlotter.cxx:1206
 TQPlotter.cxx:1207
 TQPlotter.cxx:1208
 TQPlotter.cxx:1209
 TQPlotter.cxx:1210
 TQPlotter.cxx:1211
 TQPlotter.cxx:1212
 TQPlotter.cxx:1213
 TQPlotter.cxx:1214
 TQPlotter.cxx:1215
 TQPlotter.cxx:1216
 TQPlotter.cxx:1217
 TQPlotter.cxx:1218
 TQPlotter.cxx:1219
 TQPlotter.cxx:1220
 TQPlotter.cxx:1221
 TQPlotter.cxx:1222
 TQPlotter.cxx:1223
 TQPlotter.cxx:1224
 TQPlotter.cxx:1225
 TQPlotter.cxx:1226
 TQPlotter.cxx:1227
 TQPlotter.cxx:1228
 TQPlotter.cxx:1229
 TQPlotter.cxx:1230
 TQPlotter.cxx:1231
 TQPlotter.cxx:1232
 TQPlotter.cxx:1233
 TQPlotter.cxx:1234
 TQPlotter.cxx:1235
 TQPlotter.cxx:1236
 TQPlotter.cxx:1237
 TQPlotter.cxx:1238
 TQPlotter.cxx:1239
 TQPlotter.cxx:1240
 TQPlotter.cxx:1241
 TQPlotter.cxx:1242
 TQPlotter.cxx:1243
 TQPlotter.cxx:1244
 TQPlotter.cxx:1245
 TQPlotter.cxx:1246
 TQPlotter.cxx:1247
 TQPlotter.cxx:1248
 TQPlotter.cxx:1249
 TQPlotter.cxx:1250
 TQPlotter.cxx:1251
 TQPlotter.cxx:1252
 TQPlotter.cxx:1253
 TQPlotter.cxx:1254
 TQPlotter.cxx:1255
 TQPlotter.cxx:1256
 TQPlotter.cxx:1257
 TQPlotter.cxx:1258
 TQPlotter.cxx:1259
 TQPlotter.cxx:1260
 TQPlotter.cxx:1261
 TQPlotter.cxx:1262
 TQPlotter.cxx:1263
 TQPlotter.cxx:1264
 TQPlotter.cxx:1265
 TQPlotter.cxx:1266
 TQPlotter.cxx:1267
 TQPlotter.cxx:1268
 TQPlotter.cxx:1269
 TQPlotter.cxx:1270
 TQPlotter.cxx:1271
 TQPlotter.cxx:1272
 TQPlotter.cxx:1273
 TQPlotter.cxx:1274
 TQPlotter.cxx:1275
 TQPlotter.cxx:1276
 TQPlotter.cxx:1277
 TQPlotter.cxx:1278
 TQPlotter.cxx:1279
 TQPlotter.cxx:1280
 TQPlotter.cxx:1281
 TQPlotter.cxx:1282
 TQPlotter.cxx:1283
 TQPlotter.cxx:1284
 TQPlotter.cxx:1285
 TQPlotter.cxx:1286
 TQPlotter.cxx:1287
 TQPlotter.cxx:1288
 TQPlotter.cxx:1289
 TQPlotter.cxx:1290
 TQPlotter.cxx:1291
 TQPlotter.cxx:1292
 TQPlotter.cxx:1293
 TQPlotter.cxx:1294
 TQPlotter.cxx:1295
 TQPlotter.cxx:1296
 TQPlotter.cxx:1297
 TQPlotter.cxx:1298
 TQPlotter.cxx:1299
 TQPlotter.cxx:1300
 TQPlotter.cxx:1301
 TQPlotter.cxx:1302
 TQPlotter.cxx:1303
 TQPlotter.cxx:1304
 TQPlotter.cxx:1305
 TQPlotter.cxx:1306
 TQPlotter.cxx:1307
 TQPlotter.cxx:1308
 TQPlotter.cxx:1309
 TQPlotter.cxx:1310
 TQPlotter.cxx:1311
 TQPlotter.cxx:1312
 TQPlotter.cxx:1313
 TQPlotter.cxx:1314
 TQPlotter.cxx:1315
 TQPlotter.cxx:1316
 TQPlotter.cxx:1317
 TQPlotter.cxx:1318
 TQPlotter.cxx:1319
 TQPlotter.cxx:1320
 TQPlotter.cxx:1321
 TQPlotter.cxx:1322
 TQPlotter.cxx:1323
 TQPlotter.cxx:1324
 TQPlotter.cxx:1325
 TQPlotter.cxx:1326
 TQPlotter.cxx:1327
 TQPlotter.cxx:1328
 TQPlotter.cxx:1329
 TQPlotter.cxx:1330
 TQPlotter.cxx:1331
 TQPlotter.cxx:1332
 TQPlotter.cxx:1333
 TQPlotter.cxx:1334
 TQPlotter.cxx:1335
 TQPlotter.cxx:1336
 TQPlotter.cxx:1337
 TQPlotter.cxx:1338
 TQPlotter.cxx:1339
 TQPlotter.cxx:1340
 TQPlotter.cxx:1341
 TQPlotter.cxx:1342
 TQPlotter.cxx:1343
 TQPlotter.cxx:1344
 TQPlotter.cxx:1345
 TQPlotter.cxx:1346
 TQPlotter.cxx:1347
 TQPlotter.cxx:1348
 TQPlotter.cxx:1349
 TQPlotter.cxx:1350
 TQPlotter.cxx:1351
 TQPlotter.cxx:1352
 TQPlotter.cxx:1353
 TQPlotter.cxx:1354
 TQPlotter.cxx:1355
 TQPlotter.cxx:1356
 TQPlotter.cxx:1357
 TQPlotter.cxx:1358
 TQPlotter.cxx:1359
 TQPlotter.cxx:1360
 TQPlotter.cxx:1361
 TQPlotter.cxx:1362
 TQPlotter.cxx:1363
 TQPlotter.cxx:1364
 TQPlotter.cxx:1365
 TQPlotter.cxx:1366
 TQPlotter.cxx:1367
 TQPlotter.cxx:1368
 TQPlotter.cxx:1369
 TQPlotter.cxx:1370
 TQPlotter.cxx:1371
 TQPlotter.cxx:1372
 TQPlotter.cxx:1373
 TQPlotter.cxx:1374
 TQPlotter.cxx:1375
 TQPlotter.cxx:1376
 TQPlotter.cxx:1377
 TQPlotter.cxx:1378
 TQPlotter.cxx:1379
 TQPlotter.cxx:1380
 TQPlotter.cxx:1381
 TQPlotter.cxx:1382
 TQPlotter.cxx:1383
 TQPlotter.cxx:1384
 TQPlotter.cxx:1385
 TQPlotter.cxx:1386
 TQPlotter.cxx:1387
 TQPlotter.cxx:1388
 TQPlotter.cxx:1389
 TQPlotter.cxx:1390
 TQPlotter.cxx:1391
 TQPlotter.cxx:1392
 TQPlotter.cxx:1393
 TQPlotter.cxx:1394
 TQPlotter.cxx:1395
 TQPlotter.cxx:1396
 TQPlotter.cxx:1397
 TQPlotter.cxx:1398
 TQPlotter.cxx:1399
 TQPlotter.cxx:1400
 TQPlotter.cxx:1401
 TQPlotter.cxx:1402
 TQPlotter.cxx:1403
 TQPlotter.cxx:1404
 TQPlotter.cxx:1405
 TQPlotter.cxx:1406
 TQPlotter.cxx:1407
 TQPlotter.cxx:1408
 TQPlotter.cxx:1409
 TQPlotter.cxx:1410
 TQPlotter.cxx:1411
 TQPlotter.cxx:1412
 TQPlotter.cxx:1413
 TQPlotter.cxx:1414
 TQPlotter.cxx:1415
 TQPlotter.cxx:1416
 TQPlotter.cxx:1417
 TQPlotter.cxx:1418
 TQPlotter.cxx:1419
 TQPlotter.cxx:1420
 TQPlotter.cxx:1421
 TQPlotter.cxx:1422
 TQPlotter.cxx:1423
 TQPlotter.cxx:1424
 TQPlotter.cxx:1425
 TQPlotter.cxx:1426
 TQPlotter.cxx:1427
 TQPlotter.cxx:1428
 TQPlotter.cxx:1429
 TQPlotter.cxx:1430
 TQPlotter.cxx:1431
 TQPlotter.cxx:1432
 TQPlotter.cxx:1433
 TQPlotter.cxx:1434
 TQPlotter.cxx:1435
 TQPlotter.cxx:1436
 TQPlotter.cxx:1437
 TQPlotter.cxx:1438
 TQPlotter.cxx:1439
 TQPlotter.cxx:1440
 TQPlotter.cxx:1441
 TQPlotter.cxx:1442
 TQPlotter.cxx:1443
 TQPlotter.cxx:1444
 TQPlotter.cxx:1445
 TQPlotter.cxx:1446
 TQPlotter.cxx:1447
 TQPlotter.cxx:1448
 TQPlotter.cxx:1449
 TQPlotter.cxx:1450
 TQPlotter.cxx:1451
 TQPlotter.cxx:1452
 TQPlotter.cxx:1453
 TQPlotter.cxx:1454
 TQPlotter.cxx:1455
 TQPlotter.cxx:1456
 TQPlotter.cxx:1457
 TQPlotter.cxx:1458
 TQPlotter.cxx:1459
 TQPlotter.cxx:1460
 TQPlotter.cxx:1461
 TQPlotter.cxx:1462
 TQPlotter.cxx:1463
 TQPlotter.cxx:1464