#include "TH1.h"
#include "TH2.h"
#include "TProfile.h"

#include <algorithm>

#include "QFramework/TQIterator.h"
#include "QFramework/TQTikZPlotter.h"
#include "QFramework/TQUtils.h"

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

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQTikZPlotter:
//
// The TQTikZPlotter is a plotter implemention utilizing TikZ/PGFplots instead of ROOT
//
////////////////////////////////////////////////////////////////////////////////////////////////

ClassImp(TQTikZPlotter)

//______________________________________________________________________________________________

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

  //@tags: printProcesses: print processes to the console before plotting
  if(tags.getTagBoolDefault("printProcesses",false)){
    this->printProcesses();
  }

  //@tags: useNamePrefix: prefix histogram names with the variable names. will not affect the look of the plot, but possibly required for elaborate plots to be saved in .C format
  if(tags.getTagBoolDefault("useNamePrefix",true)){
    TString tmp(histogram);
    TString prefix = TQFolder::getPathTail(tmp);
    TQStringUtils::ensureTrailingText(prefix,".");
    tags.importTagsWithoutPrefix(tags,prefix);
  }
  tags.importTags(this);
  if(histogram.Contains("=")){
    tags.importTagsWithPrefix(histogram,"input");
  } else {
    tags.setTagString("input.histogram",histogram);
  }
  
  bool success = false;
  try {
    std::ofstream os(saveAs.Data());
    if(os.good()){
      success = makePlot(os,tags);
    }
    os.close();
  } catch (const std::exception& err){
    std::cout << err.what() << std::endl;
  }

  if(tags.getTagBoolDefault("deleteObjects",true)){
    //@tags: deleteObjects: control whether plotting objects will be kept in memory after plotting (default: false for plotAndSaveAs, true for plot)
    this->deleteObjects();
  } 
  return success;
}

//______________________________________________________________________________________________

void TQTikZPlotter::histogramToTikZCoordinatesMC(std::ostream& os, TH1* hist){
  // output an MC const plot
  unsigned nbins = hist->GetNbinsX()+1;
  for(size_t i=1; i<nbins; ++i){
    os << "    ( " << hist->GetXaxis()->GetBinLowEdge(i) << " , " << hist->GetBinContent(i) << " )\n"; 
  }
  os << "    ( " << hist->GetXaxis()->GetBinLowEdge(nbins) << " , " << hist->GetBinContent(nbins-1) << " )\n"; 
}
void TQTikZPlotter::histogramErrorsToTikZCoordinates(std::ostream& os, TH1* hist, bool up){
  // output the +1sigma / -1sigma variation of an MC const plot
  unsigned nbins = hist->GetNbinsX()+1;
  for(size_t i=1; i<nbins; ++i){
    os << "    ( " << hist->GetXaxis()->GetBinLowEdge(i) << " , " << hist->GetBinContent(i) + (up ? hist->GetBinError(i) : -hist->GetBinError(i)) << " )\n"; 
  }
  os << "    ( " << hist->GetXaxis()->GetBinLowEdge(nbins) << " , " << hist->GetBinContent(nbins-1) + (up ? hist->GetBinError(nbins-1) : -hist->GetBinError(nbins-1)) << " )\n"; 
}

void TQTikZPlotter::histogramToTikZCoordinatesData(std::ostream& os, TH1* hist){
  // output a data plot with error bars
  unsigned nbins = hist->GetNbinsX()+1;
  for(size_t i=1; i<nbins; ++i){
    os << "    ( " << hist->GetXaxis()->GetBinCenter(i) << " , " << hist->GetBinContent(i) << " ) +- ( " << 0.5*(hist->GetXaxis()->GetBinWidth(i)) << " , " << hist->GetBinError(i) << " )\n"; 
  }
}

//______________________________________________________________________________________________

bool TQTikZPlotter::makePlot(std::ostream& output, TQTaggable& tags){
  // master-function controlling the plotting

  // read a few tags
  // bool verbose = tags.getTagBoolDefault("verbose",false); // BW: hashed (unused variable)
  bool standalone  = tags.getTagBoolDefault("standalone",true);
  bool showSub = false;
  bool showRatio = tags.getTagBoolDefault ("style.showRatio",false);
  bool showDminusB = tags.getTagBoolDefault ("style.showDminusB",false);
  bool showOptScan = tags.getTagBoolDefault ("style.showOptScan",false);
  if(showRatio || showDminusB || showOptScan){
    showSub = true;
  }
  bool showErrorEnds = tags.getTagBoolDefault("style.showErrorEnds",false);
  
  // collect the objects
  //TObjArray* histos = this->collectHistograms(tags); // BW: hashed (unused variable)
  TH1* hMaster = this->getObject<TH1>("Graph_master");
  if(!hMaster) return false;
  this->setAxisLabels(tags);

  // create header
  if(standalone) output << "\\documentclass[tikz,border=3pt]{standalone}\n";
  output << "%%% this plot was automatically generated on " << TQUtils::getTimeStamp() << " using CAFCore\n";
  if(!standalone) output << "% add this to your document preamble\n";
  // packages and libraries
  output << (standalone ? "" : "%") << "\\usepackage{pgfplots}\n";
  output << (standalone ? "" : "%") << "\\usepackage{sansmath}\n";
  output << (standalone ? "" : "%") << "\\usepgfplotslibrary{fillbetween}\n";
  output << (standalone ? "" : "%") << "\\usetikzlibrary{patterns}\n";
  // plot styles
  output << (standalone ? "" : "%") << "\\tikzset{datapoints/.style={draw=black,solid,/pgfplots/.cd,only marks,error bars/y dir = both,error bars/y explicit,";
  if(!showErrorEnds)  output << "error bars/error mark options = {rotate=90,mark size=0pt}}}";
  output << "\n";
  output << (standalone ? "" : "%") << "\\tikzset{mcstack/.style={/pgfplots/.cd,stack plots=y,const plot, no marks}}\n";
  output << (standalone ? "" : "%") << "\\tikzset{mcnostack/.style={/pgfplots/.cd,const plot, no marks}}\n";
  // legend entry styles
  output << (standalone ? "" : "%") << "\\pgfplotsset{/pgfplots/fillbox/.style={legend image code/.code={\\fill[draw=none,no markers] (.0em,-.5em) rectangle (1.7em,.5em); } } }\n";
  output << (standalone ? "" : "%") << "\\pgfplotsset{/pgfplots/fillboxline/.style={legend image code/.code={\\draw[draw=none,no markers] (.0em,-.5em) rectangle (1.7em,.5em); \\draw[fill=none] (0.0em,0.0em) -- (1.7em,0.0em); } } }\n";
  output << (standalone ? "" : "%") << "\\pgfplotsset{/pgfplots/datapoint/.style={legend image code/.code={\\draw";
  if(showErrorEnds) output << "[|-|]";
  output << " (.85em,.5em) -- (.85em,-.5em) node[pos=0.5,anchor=center,circle,fill,inner sep=1pt] {} ; } } }\n";
  // begin the document
  if(standalone) output <<"\\begin{document}\n";

  // obtain the geometry
  int width  = tags.getTagIntegerDefault("geometry.canvas.width",400);
  int height = tags.getTagIntegerDefault("geometry.canvas.height",300);
  double subpadRatio = tags.getTagDoubleDefault("geometry.sub.height",0.35);

  // initialize the picture environment
  output << "\\begin{tikzpicture}[font={\\fontfamily{qhv}\\selectfont},fill between/on layer={main}]\n";
  output << "\\pgfplotsset{axis on top}\n";
  output << "\\sansmath\n";

  // collect the styles and write out the color definitions
  makeStyles(tags,output);
  output << TQStringUtils::getColorDefStringLaTeX("mainErrorBand",14) << "\n";
  output << TQStringUtils::getColorDefStringLaTeX("subErrorBand",kOrange-2) << "\n";
  
  // create the axis of the main pad
  output << "\\begin{axis}[name=main,height=" << height << "pt,width=" << width << "pt,ymin=0,enlarge x limits=false,clip=false,\n";
  output << "    domain=" << hMaster->GetXaxis()->GetXmin() << ":" << hMaster->GetXaxis()->GetXmax() << ",\n";
  output << "    legend style={legend columns=" << tags.getTagIntegerDefault ("style.nLegendCols",1) << ",fill=none,draw=none},legend cell align={left},\n";
  if(!showSub) output << "    xlabel={"<<hMaster->GetXaxis()->GetTitle()<<"},x label style={at={(axis description cs:1.0,-0.01)},anchor=north east},\n";
  else         output << "    xticklabels={},\n";
  output << "    ylabel={"<<hMaster->GetYaxis()->GetTitle()<<"},y label style={at={(axis description cs:0.00,1.0)},anchor=south east},\n";
  output << "]\n";
  
  // draw the contents of the main pad
  drawStack(tags,output);

  // draw the labels
  drawLabels(tags,output);

  // close the main pad
  output << "\\end{axis}\n";

  if(showSub){
    // special if for optimization scans
    TQHistogramUtils::FOM FOMmode = TQHistogramUtils::kUndefined;
    //@tag:optScan.FOMmode: figure of merit to be used. currently available are: s/sqrt(s+b),s/b,poisson,s/sqrt(b),s/sqrt(b+db2)
    //@tag:style.FOMmode: deprecated, use optScan.FOMmode
    if(showOptScan){
      TString fommodestr = tags.getTagStringDefault("optScan.FOMmode",tags.getTagStringDefault ("style.FOMmode","s/sqrt(b)"));
      FOMmode = TQHistogramUtils::readFOM(fommodestr);
      if(FOMmode == TQHistogramUtils::kUndefined){
        WARNclass("unknown figure of merit '%s'!",fommodestr.Data());
        showOptScan = false;
      }
    }

    // create the axis of the sub pad
    output << "\\begin{axis}[name=sub,at=(main.south west), anchor=north west,height=" << subpadRatio*height << "pt,width=" << width << "pt,enlarge x limits=false,clip=false,\n";
    output << "    domain=" << hMaster->GetXaxis()->GetXmin() << ":" << hMaster->GetXaxis()->GetXmax() << ",\n";
    if(showOptScan)   output << "    legend style={legend columns=1,fill=none,draw=none},legend cell align={left},\n";
    output << "    xlabel={"<<hMaster->GetXaxis()->GetTitle()<<"},x label style={at={(axis description cs:1.0,-0.01)},anchor=north east},\n";
    output << "    ylabel={";
    // choose the label dynamically
    if(showRatio)        output << "Data/SM";
    else if(showDminusB) output << "Data-Bkg.";
    else if(showOptScan) output << TQHistogramUtils::getFOMTitleLaTeX(FOMmode);
    output <<"},y label style={at={(axis description cs:0.00,1.0)},anchor=south east},\n";
    output << "]\n";
    
    // draw the contents of the sub pad
    if     (showRatio)   drawRatio  (tags,output);
    else if(showDminusB) drawDminusB(tags,output);
    else if(showOptScan) drawOptScan(tags,output,FOMmode);

    // close the sub pad
    output << "\\end{axis}\n";
  }
  
  // finalize the picture
  output << "\\end{tikzpicture}\n";
  if(standalone){
    output << "\\end{document}\n";
  }

  // cleanup temporary objects
  this->f_stack.clear();
  this->f_data.clear();
  this->f_signal.clear();

  return true;
}

//______________________________________________________________________________________________

void TQTikZPlotter::makeStyles(TQTaggable& tags,std::ostream& output){
  // collect all the styles and definitions
  TH1* hMaster = this->getObject<TH1>("Graph_master");

  // the total stack and error band histograms
  TH1* hTotalStack = TQHistogramUtils::copyHistogram(hMaster,"totalStack");
  TH1* hTotalBkg = TQHistogramUtils::copyHistogram(hMaster,"totalBkg");
  TString bandStyle = "color=mainErrorBand";

  bandStyle.Append(",pattern=");  
  int pattern = tags.getTagIntegerDefault("style.main.totalStackError.fillStyle",3254);
  switch(pattern % 100){
  case  5: bandStyle.Append("horizontal lines"); break;
  case 50: bandStyle.Append("vertical lines"); break;
  case 44: bandStyle.Append("crosshatch"); break;
  case 54: bandStyle.Append("north west lines"); break;
  case 45: bandStyle.Append("north east lines"); break;
  default: 
    WARNclass("pattern not implemented: %d",pattern);
    bandStyle.Append("none");
  }

  bandStyle.Append(",draw=");
  int color = tags.setTagInteger("style.main.totalStack.lineColor",kBlue);
  if(color == kWhite){
    bandStyle.Append("none");
  } else if(color == kBlue){
    bandStyle.Append("blue");;
  } else if(color == kBlack){
    bandStyle.Append("black");
  } else {
    output << TQStringUtils::getColorDefStringLaTeX("drawtotalStack",color) << "\n";
    bandStyle.Append("drawtotalStack");
  }
  bandStyle.Append(",thick,");
  
  f_styles[hTotalStack] = bandStyle;
  f_styles[hTotalBkg]   = bandStyle;


  TQTaggableIterator itr(this->fProcesses);
  while(itr.hasNext()){
    // loop over all processes
    TQNamedTaggable* process = itr.readNext();
    if(!process) continue;
    bool isBkg = process->getTagBoolDefault(".isBackground",false);
    bool isSig =  process->getTagBoolDefault(".isSignal",false);
    // bool isData =  process->getTagBoolDefault(".isData",false); // BW: hashed (unused variable)
    if(process->getTagBoolDefault("stack", isBkg) || (isSig && tags.getTagBoolDefault ("style.autoStackSignal",false))){
      TH1 * h = this->getObject<TH1>(this->makeHistogramIdentifier(process));
      if (!h) continue;
      // if this is a background or otherwise stacked
      // this is an MC histogram, collect draw and fill color
      TString processStyle;
      TString processName = process->getTagStringDefault(".name",process->GetName());
      if(h->GetFillStyle() == 1001){
        int fillColor = h->GetFillColor();
        TString fillColorName = processName;
        fillColorName.Prepend("fill");
        TString fillColorDef = TQStringUtils::getColorDefStringLaTeX(fillColorName,fillColor);
        output << fillColorDef << "\n";
        processStyle.Append("fill=");
        processStyle.Append(fillColorName);
        processStyle.Append(",");
      } else {
        processStyle.Append("fill=none,");
      }
      int drawColor = h->GetLineColor();
      if(drawColor != kBlack){
        TString drawColorName = processName;
        drawColorName.Prepend("draw");
        TString drawColorDef = TQStringUtils::getColorDefStringLaTeX(drawColorName,drawColor);
        output << drawColorDef << "\n";
        processStyle.Append("draw=");
        processStyle.Append(drawColorName);
        processStyle.Append(",");
      } else {
        processStyle.Append("draw=black,");
      }
      f_stack.push_back(h);
      f_styles[h] = processStyle;
      hTotalStack->Add(h);
      if(isBkg) hTotalBkg->Add(h);
    } else if (process->getTagBoolDefault(".isSignal",false)){
      TH1 * h = this->getObject<TH1>(this->makeHistogramIdentifier(process));
      if(!h) continue;
      // if this is a signal
      // this is an MC histogram, collect draw and fill color
      TString sigStyle;
      int drawcolor = h->GetLineColor();
      if(drawcolor != kBlack){
        TString drawColorName = tags.getTagStringDefault(".name",TQFolder::makeValidIdentifier(process->GetName()));
        drawColorName.Prepend("draw");
        TString style = "draw=";
        style.Append(drawColorName);
        style.Append(",");
        TString drawColorDef = TQStringUtils::getColorDefStringLaTeX(drawColorName,drawcolor);
        output << drawColorDef << "\n";
        sigStyle.Append(style);
      } else {
        sigStyle.Append("draw=black,");
      }
      if(h->GetFillStyle() == 1001){
        int fillcolor = h->GetFillColor();
        TString drawColorName = tags.getTagStringDefault(".name",TQFolder::makeValidIdentifier(process->GetName()));
        drawColorName.Prepend("fill");
        TString style = "fill=";
        style.Append(drawColorName);
        style.Append(",");
        TString drawColorDef = TQStringUtils::getColorDefStringLaTeX(drawColorName,fillcolor);
        output << drawColorDef << "\n";
        sigStyle.Append(style);
      } else {
        sigStyle.Append("fill=none,");
      }
      f_signal.push_back(h);
      f_styles[h] = sigStyle;
      if(tags.getTagBoolDefault("style.stackSignal")) hTotalStack->Add(h);
    } else if(process->getTagBoolDefault(".isData",false)){
      TH1 * h = this->getObject<TH1>(this->makeHistogramIdentifier(process));
      f_data.push_back(h);
      if(!h) continue;
      this->applyStyle(tags,h,"main.data");
      // if this is a data histogram
      // we only care for the marker color
      int color = h->GetMarkerColor();
      TString style;
      if(color != kBlack){
        TString drawColorName = tags.getTagStringDefault(".name",TQFolder::makeValidIdentifier(process->GetName()));
        drawColorName.Prepend("mark");
        TString style = "draw=";
        style.Append(drawColorName);
        style.Append(",");
        style.Append("mark=*,");
        style.Append("mark options={fill=");
        style.Append(drawColorName);
        style.Append("},");
        style.Append("error bars/error mark options/.append style={solid,draw=");
        style.Append(drawColorName);
        style.Append("},");
        TString drawColorDef = TQStringUtils::getColorDefStringLaTeX(drawColorName,color);
        output << drawColorDef << "\n";
      } else {
        style = "draw=black,mark=*,mark options={fill=black},error bars/error mark options/.append style={solid,draw=black},";
      }
      f_styles[h] = style;
    }
  }
}

//______________________________________________________________________________________________

void TQTikZPlotter::drawStack(TQTaggable& tags,std::ostream& output){
  // draw the stack on the main pad
  TH1* hMaster = this->getObject<TH1>("Graph_master");
  TH1* hTotalStack = this->getObject<TH1>("totalStack");
  if(!hMaster) return;
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  // preparations 
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  // set the errors
  if(tags.hasTag("errors.showSys")){
    this->includeSystematics(tags);
  }
  this->setErrors(tags,tags.getTagStringDefault("errors.source","totalBkg"));

  std::vector<TH1*> v_stack(f_stack);
  // sort the histograms to be stacked by ascending integral (sum of weights)
  if (!tags.getTagBoolDefault("style.manualStacking",false) && tags.getTagBoolDefault("style.autoStack",true)){
    std::sort(v_stack.begin(),v_stack.end(),[&](TH1* a, TH1* b){ return a->GetSumOfWeights() <= b->GetSumOfWeights();});
  }
  bool reverseStacking = tags.getTagBoolDefault ("style.reverseStacking",false );

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  // legend
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  // add the data to the legend
  std::vector<std::pair<TString,TString> > legend;
  for (size_t iHist = 0; iHist < f_data.size() ; iHist++){
    TH1* h = f_data[iHist];
    TString style = f_styles[h];
    legend.push_back(std::make_pair("datapoint,"+style,h->GetTitle()));
  }
  
  // add the error band to the legend
  bool statMcErrors = tags.getTagBoolDefault("errors.drawStatMC",true );
  bool sysMcErrors = tags.getTagBoolDefault("errors.drawSysMC",false ) || tags.hasTag("errors.showSys");
  TString legendTotalBkgLabel = tags.getTagStringDefault ("labels.totalStack", "SM");
  legendTotalBkgLabel = " " + tags.getTagStringDefault ("labels.legendTotalBkg", legendTotalBkgLabel); // overwrite if you explicitly want it different in legend
  if(tags.getTagBoolDefault("legend.showTotalBkgErrorType",true)){
    if (statMcErrors && sysMcErrors)
      legendTotalBkgLabel.Append(" (sys $\\oplus$ stat)");
    else if (sysMcErrors)
      legendTotalBkgLabel.Append(" (sys)");
    else if (statMcErrors)
      legendTotalBkgLabel.Append(" (stat)");
  }
  legend.push_back(std::make_pair(TString(tags.setTagInteger("style.main.totalStack.lineColor",kBlue) == kWhite ? "fillbox" : "fillboxline")+","+f_styles[hTotalStack],legendTotalBkgLabel));
  
  // add the stack to the legend
  for (int iHist = reverseStacking ? (int) v_stack.size() : 0; reverseStacking ? (iHist >= 0) : (iHist < (int) v_stack.size()) ; reverseStacking ? iHist-- : iHist++){
    TH1* h = dynamic_cast<TH1*>(v_stack.at(iHist));
    TString style = f_styles[h];
    legend.push_back(std::make_pair("fillbox,"+style,h->GetTitle()));
  } 

  // add the signal to the legend
  for (size_t iHist = 0; iHist < f_signal.size() ; iHist++){
    TH1* h = f_signal[iHist];
    TString style = f_styles[h];
    legend.push_back(std::make_pair("fillbox,"+style,h->GetTitle()));
  }

  // output all legend entries
  for(const auto& entry:legend){
    output << "\\addlegendimage{" << entry.first << "}\n";
    output << "\\addlegendentry{" << entry.second << "}\n";
  }

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  // draw stack, signal and data
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  // draw stack
  for (int iHist = reverseStacking ? (int) v_stack.size() : 0; reverseStacking ? (iHist >= 0) : (iHist < (int) v_stack.size()) ; reverseStacking ? iHist-- : iHist++){
    TH1* h = v_stack[iHist];
    TString style = f_styles[h];
    output << "\\addplot+[mcstack," << style <<"] coordinates {\n";
    histogramToTikZCoordinatesMC(output,h);
    output << "}\\closedcycle;\n";
  } 
  // draw signal
  for (size_t iHist = 0; iHist < f_signal.size() ; iHist++){
    TH1* h = f_signal[iHist];
    TString style = f_styles[h];
    output << "\\addplot[";
    if(tags.getTagBoolDefault("style.stackSignal",false)){
      output << "mcstack";
    } else {
      output << "mcnostack";
    }
    output << "," << style <<"] coordinates {\n";
    histogramToTikZCoordinatesMC(output,h);
    output << "}\\closedcycle;\n";
  }

  // draw error band
  output << "\\addplot[const plot,draw=none,fill=none,name path=lower] coordinates {\n";
  histogramErrorsToTikZCoordinates(output,hTotalStack,false);
  output << "};\n";
  output << "\\addplot[const plot,draw=none,fill=none,name path=upper] coordinates {\n";
  histogramErrorsToTikZCoordinates(output,hTotalStack,true);
  output << "};\n";
  output << "\\addplot[const plot," << f_styles[hTotalStack] << ",draw=none] fill between [of=lower and upper];\n";
  bool showTotalBkg = tags.getTagBoolDefault ("style.showTotalBkg",true);
  if(showTotalBkg) {
    output << "\\addplot[const plot," << f_styles[hTotalStack] << ",fill=none] coordinates {\n";
    histogramToTikZCoordinatesMC(output,hTotalStack);
    output << "};\n";
  }
  
  // draw data
  for (size_t iHist = 0; iHist < f_data.size() ; iHist++){
    TH1* h = f_data[iHist];
    TString style = f_styles[h];
    output << "\\addplot[datapoints," << style <<"] coordinates {\n";
    histogramToTikZCoordinatesData(output,h);
    output << "}\\closedcycle;\n";
  }

}

//______________________________________________________________________________________________

void TQTikZPlotter::drawLabels(TQTaggable& tags,std::ostream& output){
  // draw the labels given by the tags
  bool drawlabels = tags.getTagBoolDefault("style.showLabels",true);

  // locations of the labels
  double x = tags.getTagDoubleDefault("style.labels.xOffset",0.05);
  double y = tags.getTagDoubleDefault("style.labels.yPos",0.95);
 
  // the ATLAS labels
  //@tag:labels.drawATLAS: decide whether to draw the 'ATLAS' label
  //@tag:labels.atlas: which ATLAS label to use (Private, work in progress, Internal, Preliminary, ... - default:'Private')
  //@tag:labels.atlas.xOffset : horizontal offset between ATLAS label and its addition. (default: 0.16)
  bool drawATLAS = tags.getTagBoolDefault ("labels.drawATLAS",drawlabels);
  if (drawATLAS) {
    output << "\\node[anchor = west, font={\\fontfamily{phv}\\fontseries{b}\\selectfont}] at (axis description cs:" << x << "," << y << ") {" << tags.getTagStringDefault("labels.drawATLAS.text","ATLAS") << "};\n";
  }
  TString atlasLabel = tags.getTagStringDefault ("labels.atlas","Private");
  if (drawATLAS && !atlasLabel.IsNull()){
    output << "\\node[anchor = west] at (axis description cs:" << x + tags.getTagDoubleDefault("labels.atlas.xOffset",0.16) << "," << y << ") {" << atlasLabel << "};\n";
  }

  // collect the NF information
  TString nfLabel = "";
  //@tag:labels.drawNFInfo: decide whether to draw information on which NFs were applied
  if(tags.getTagBoolDefault ("labels.drawNFInfo",false)){
    TString tmpLabel = tags.getTagStringDefault("labels.nfInfo","\\textcolor{red}{(NF applied for %s)}");
    TString nflist = this->getScaleFactorList(tags.getTagStringDefault("input.bkg",""));
    if(!nflist.IsNull()){
      nfLabel = TString::Format(tmpLabel.Data(),nflist.Data());
    }
  }

  // draw the info label 
  //@tag:labels.drawInfo: decide whether to draw the technical info tag on the top right of the plot
  TString infoLabel = tags.getTagBoolDefault ("labels.drawInfo",drawlabels) ? tags.getTagStringDefault ("labels.info",TString::Format("Plot: \"%s\"", tags.getTagStringDefault("input.name","histogram").Data())) : ""; 
  if (!infoLabel.IsNull()){
    // draw the info label
    if(!nfLabel.IsNull()){
      infoLabel.Prepend(" ");
      infoLabel.Prepend(nfLabel);
    }
    output << "\\node[anchor = south east] at (axis description cs:1,1) {" << infoLabel.Data() << "};\n";    
  }
  
  // draw all remaining lables
  double marginStep = tags.getTagDoubleDefault("style.labels.marginStep",0.06);
  // double labelTextScale = tags.getTagDoubleDefault("style.labels.scale",0.85); // BW: hashed (unused variable)
  if(drawlabels){
    TQIterator itr(tags.getTagList("labels"),true);
    size_t index = 1;
    while(itr.hasNext()){
      TObject* obj = itr.readNext();
      if(!obj) break;
      output << "\\node[anchor = west] at (axis description cs:" << x << "," << y - marginStep * index << ") {" << TQStringUtils::convertROOTTeX2LaTeX(obj->GetName()) << "};\n";
      index++;
    }
  }
}

//______________________________________________________________________________________________

void TQTikZPlotter::drawRatio  (TQTaggable& tags,std::ostream& output){
  // draw a ratio-plot in the sub-pad

  bool invertRatio = tags.getTagBoolDefault("style.invertRatio",false);
  TString totalStackLabel = tags.getTagStringDefault ("labels.totalStack", "SM");
  // get the denominator
  TString ratioDenominator = tags.getTagStringDefault("style.ratio.denominator","totalStack");
  TH1* denominator = this->getObject<TH1>(ratioDenominator);
  if(!denominator) return;

  // get the error band
  TH1* error = TQHistogramUtils::copyHistogram(denominator,"ratio_error");
  TQHistogramUtils::divideHistogramWithoutError(error,denominator);
  output << "\\addplot[const plot,draw=none,fill=none,name path=ratiolower] coordinates {\n";
  histogramErrorsToTikZCoordinates(output,error,false);
  output << "};\n";
  output << "\\addplot[const plot,draw=none,fill=none,name path=ratioupper] coordinates {\n";
  histogramErrorsToTikZCoordinates(output,error,true);
  output << "};\n";
  output << "\\addplot[const plot,draw=none,fill=subErrorBand] fill between [of=ratiolower and ratioupper];\n";
  output << "\\addplot[draw=red] {1};\n";
  output << "\\addplot[draw=black,dashed] {1.05};\n";
  output << "\\addplot[draw=black,dashed] {0.95};\n";

  // get the numerator(s)
  TString dataLabel("");
  tags.getTagString("labels.numerator",dataLabel);
  for(size_t i=0; i<f_data.size(); ++i){
    TH1 * h_data = f_data[i];
    // get style and label
    TString style = f_styles[h_data];
    if(dataLabel.IsNull()) dataLabel = h_data->GetTitle();
    tags.getTagString("labels.data",dataLabel);
    
    // calculate the ratio
    TH1* h_ratio = TQHistogramUtils::copyHistogram(h_data,TString::Format("%s_ratio",h_data->GetName()));
    TQHistogramUtils::divideHistogramWithoutError(h_ratio,denominator);
    if(invertRatio) TQHistogramUtils::power(h_ratio,-1);
    
    // plot the ratio
    output << "\\addplot[datapoints," << style <<"] coordinates {\n";
    histogramToTikZCoordinatesData(output,h_ratio);
    output << "}\\closedcycle;\n";
  }
}
 
void TQTikZPlotter::drawDminusB(TQTaggable& tags,std::ostream& output){
  // draw a data-minus-background plot on the sub pad

  // the subtraction is usually the background
  TString subtractionName = tags.getTagStringDefault("style.DminusB.subtraction","totalBkg");
  TH1* subtraction = this->getObject<TH1>(subtractionName);
  if(!subtraction) return;
  // the source of the error band is usually also the background
  TString errorSourceName = tags.getTagStringDefault("style.DminusB.errors","totalBkg");
  TH1* errorSource = this->getObject<TH1>(errorSourceName);
  if(!errorSource) return;
  
  // sort signals by integral to have smallest contribution in front
  std::vector<TH1*> v_signal(f_signal);;
  std::sort(v_signal.begin(),v_signal.end(),[&](TH1* a, TH1* b){ return a->GetSumOfWeights() >= b->GetSumOfWeights();});
  
  // loop over all signals and plot them
  for(auto h:v_signal){
    TString style = f_styles[h];
    output << "\\addplot+[mcnostack," << style <<"] coordinates {\n";
    histogramToTikZCoordinatesMC(output,h);
    output << "}\\closedcycle;\n";
  } 
   
  // create the error histogram 
  TH1* error = TQHistogramUtils::copyHistogram(errorSource);
  TQHistogramUtils::addHistogramWithoutError(error,subtraction,-1.);
  // plot the error band
  output << "\\addplot[const plot,draw=none,fill=none,name path=dmblower] coordinates {\n";
  histogramErrorsToTikZCoordinates(output,error,false);
  output << "};\n";
  output << "\\addplot[const plot,draw=none,fill=none,name path=dmbupper] coordinates {\n";
  histogramErrorsToTikZCoordinates(output,error,true);
  output << "};\n";
  output << "\\addplot[const plot," << f_styles[errorSource] << ",draw=none] fill between [of=dmblower and dmbupper];\n";
  bool showTotalBkg = tags.getTagBoolDefault ("style.showTotalBkg",true);
  if(showTotalBkg) {
    output << "\\addplot[const plot," << f_styles[errorSource] << ",fill=none] coordinates {\n";
    histogramToTikZCoordinatesMC(output,error);
    output << "};\n";
  }

  // loop over all data histograms and plot them
  for(auto h:f_data){
    TH1 * h_data = TQHistogramUtils::copyHistogram(h,TString::Format("%s_minus_bkg",h->GetName()));
    TQHistogramUtils::addHistogramWithoutError(h_data,subtraction,-1.);
    TString style = f_styles[h];
    output << "\\addplot+[datapoints," << style <<"] coordinates {\n";
    histogramToTikZCoordinatesData(output,h_data);
    output << "}\\closedcycle;\n";
    delete h_data;
  }
}

//__________________________________________________________________________________|___________

void TQTikZPlotter::drawOptScan(TQTaggable& tags,std::ostream& output,TQHistogramUtils::FOM FOMmode){
  // draw a cut optimization scan in the sub-pad
  bool verbose = tags.getTagBoolDefault("verbose",false);

  if(f_signal.size() < 1){
    ERRORclass("cannot perform optimization scan unless at least one signal contribution is scheduled!");
    return;
  }
  if(f_signal.size() > 1){
    WARNclass("more than one signal contribution scheduled, using first one arbitrarily!");
  }

  TH1* hTotalStack = this->getObject<TH1>("totalStack");
  if(!hTotalStack) return;
  TH1* hSig = f_signal[0];
  if(!hSig) return;

  // figure of merit (FOM) plot. e.g. S/sqrt(B) and etc. one can implement more
  TH1* hFOMl = 0;
  TH1* hFOMr = 0;
  TH1* hFOM = 0;

  //@tag:optScan.FOMbbb: evaluate the figure-of-merit bin-by-bin instead of integrated left and right (default:false)
  //@tag:style.FOMbbb: deprecated, use optScan.FOMbbb
  bool binByBin = tags.getTagBoolDefault("optScan.FOMbbb",tags.getTagBoolDefault ("style.FOMbbb",false));
  bool drawLegend = !binByBin;
  
  std::vector<TH1*> bkgSystHistos;
  collectOptScanSimplifiedSystHistograms(bkgSystHistos, tags); //TODO? if this returns false something was wrong and no syst histograms are provided -> should abort?
  
  if(binByBin){
    if(verbose){
      VERBOSEclass("drawing bin-by-bin significances with FOM=%s for S=%s and B=%s",TQHistogramUtils::getFOMTitleROOT(FOMmode).Data(),hSig->GetTitle(),hTotalStack->GetTitle());
    }
    hFOM = TQHistogramUtils::getFOMHistogram(FOMmode,hSig, hTotalStack, 0, bkgSystHistos);
    this->addObject(hFOM,"hist_FOM_bbb");
    this->f_styles[hFOM] = "draw=green";
  } else {
    if(verbose){
      VERBOSEclass("drawing optimization scan with FOM=%s for S=%s and B=%s",TQHistogramUtils::getFOMTitleROOT(FOMmode).Data(),hSig->GetTitle(),hTotalStack->GetTitle());
    }
    hFOMl = TQHistogramUtils::getFOMScan(FOMmode,hSig, hTotalStack, true,0.05,verbose, bkgSystHistos);
    this->f_styles[hFOMl] = "draw=red";
    hFOMr = TQHistogramUtils::getFOMScan(FOMmode,hSig, hTotalStack, false,0.05,verbose, bkgSystHistos);
    this->f_styles[hFOMr] = "draw=blue";
    //@tag:optScan.autoselect: select the optimization scan (left,right) that is better suited for every histogram and only show that one (default:false)
    if(tags.getTagBoolDefault("optScan.autoselect",false)){
      if(verbose) VERBOSEclass("autoselecting opt scan");
      if(TQHistogramUtils::hasGreaterMaximumThan(hFOMr,hFOMl)){
        if(verbose) VERBOSEclass("removing left-hand FOM histogram");
        this->addObject(hFOMr,"hist_FOM");
        delete hFOMl;
        hFOMl = NULL;
      } else {
        if(verbose) VERBOSEclass("removing right-hand FOM histogram");
        this->addObject(hFOMl,"hist_FOM");
        delete hFOMr;
        hFOMr = NULL;
      }
    } else {
      if(verbose) VERBOSEclass("using all opt scans");
      this->addObject(hFOMl,"hist_FOM_left");
      this->addObject(hFOMr,"hist_FOM_right");
    }
  }
  
  //cleanup
  for (TH1* toDel : bkgSystHistos) {
    delete toDel;
  }
  bkgSystHistos.clear(); //just to make sure the otherwise dangling pointers can not accessed anymore afterwards...


  if(drawLegend){
    std::vector<std::pair<TString,TString> > legend;
    if(hFOM)  legend.push_back(std::make_pair("no markers,green","bin-by-bin"));
    if(hFOMl) legend.push_back(std::make_pair("no markers,red","$\\rightarrow$ cut"));
    if(hFOMr) legend.push_back(std::make_pair("no markers,blue","$\\leftarrow$ cut"));
    
    // output all legend entries
    for(const auto& entry:legend){
      output << "\\addlegendimage{" << entry.first << "}\n";
      output << "\\addlegendentry{" << entry.second << "}\n";
    }
  }

  // set style
  if (hFOM) {
    //@tag:style.optScan.default.*: control styling of the auto-selected FOM graph
    if(verbose) VERBOSEclass("drawing FOM histogram");
    output << "\\addplot[const plot," << f_styles[hFOM] << ",fill=none] coordinates {\n";
    histogramToTikZCoordinatesMC(output,hFOM);
    output << "};\n";
  }
  if (hFOMl) {
    //@tag:style.optScan.left.*: control styling of the left-hand-side (lower) FOM graph
    if(verbose) VERBOSEclass("drawing FOM histogram (lhs)");
    output << "\\addplot[const plot," << f_styles[hFOMl] << ",fill=none] coordinates {\n";
    histogramToTikZCoordinatesMC(output,hFOMl);
    output << "};\n";
  }
  if (hFOMr) {
    //@tag:style.optScan.right.*: control styling of the right-hand-side (upper) FOM graph
    if(verbose) VERBOSEclass("drawing FOM histogram (rhs)");
    output << "\\addplot[const plot," << f_styles[hFOMr] << ",fill=none] coordinates {\n";
    histogramToTikZCoordinatesMC(output,hFOMr);
    output << "};\n";
  }

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