#include "QFramework/TQLibrary.h"
#include "QFramework/TQCutflowPlotter.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQIterator.h"
ClassImp(TQCutflowPlotter)
TQCutflowPlotter::TQCutflowPlotter(TQSampleFolder* sf) : TQPresenter(sf) {
}
TQCutflowPlotter::TQCutflowPlotter(TQSampleDataReader* reader) : TQPresenter(reader) {
}
bool TQCutflowPlotter::writeToFile(const TString& filename, const TString& tags){
TQTaggable tmp(tags);
return this->writeToFile(filename,tmp);
}
bool TQCutflowPlotter::writeToFile(const TString& filename, TQTaggable& tags){
tags.importTags(this);
std::ofstream ofile(filename);
if(!ofile.is_open()){
return false;
}
TString format = "tikz";
tags.getTagString("format",format);
format.ToLower();
if(format.CompareTo("tikz") == 0){
this->writeTikZHead(ofile,tags);
this->writeTikZBody(ofile,tags);
this->writeTikZFoot(ofile,tags);
} else if(format.CompareTo("plain") == 0){
this->writePlain(ofile,tags);
} else {
ofile.close();
return false;
}
ofile.close();
return true;
}
void TQCutflowPlotter::writeTikZHead(std::ostream& out, TQTaggable& tags){
tags.importTags(this);
if(tags.getTagBoolDefault("standalone",true)){
out << "\\documentclass {standalone}" << std::endl;
out << "\\usepackage{pgfplots, pgfplotstable}" << std::endl;
out << "\\pgfplotsset{compat=1.8} " << std::endl;
out << "\\pgfplotsset{single xbar legend/.style={legend image code/.code={\\draw[##1,/tikz/.cd,bar width=6pt,bar shift=0pt,xbar] plot coordinates {(0.8em,0pt)};}}}" << std::endl;
out << "\\begin{document}" << std::endl;
}
}
void TQCutflowPlotter::writePlain(std::ostream& out, TQTaggable& tags){
tags.importTags(this);
TString sep = tags.getTagStringDefault("style.plain.sep",",");
out << tags.getTagStringDefault("style.plain.leadCellContent","Cut/Process");
TQTaggableIterator processes(this->fProcesses);
while(processes.hasNext()){
TQTaggable* process = processes.readNext();
if(process){
TString processPath;
if(process->getTagString(".path",processPath)){
processPath = tags.replaceInText(processPath);
if(TQFolder::isValidPath(processPath,true,true,true)){
out << sep << processPath;
}
}
}
}
out << std::endl;
TQTaggableIterator cuts(this->fCuts);
while(cuts.hasNext()){
TQTaggable* cut = cuts.readNext();
if(!cut) continue;
TString cutTitle, cutName;
if(cut->getTagString(".name",cutName)){
if(cutName.BeginsWith("|")) continue;
out << cutName;
std::vector<double> numbers;
processes.reset();
while(processes.hasNext()){
TQTaggable* process = processes.readNext();
if(process){
TString processPath;
if(process->getTagString(".path",processPath)){
processPath = tags.replaceInText(processPath);
if(TQFolder::isValidPath(processPath,true,true,true)){
TQCounter * counter = fReader->getCounter(processPath, cutName,&tags);
if (counter) {
double number = counter->getCounter();
if(TQUtils::isNum(number)) numbers.push_back(number);
else numbers.push_back(0.);
delete counter;
} else {
numbers.push_back(0.);
}
}
}
}
}
if(tags.getTagBoolDefault("style.normalize",false)){
double normalization = 0.;
for(size_t i=0; i<numbers.size(); i++){
normalization += numbers[i];
}
if(normalization > 0){
for(size_t i=0; i<numbers.size(); i++){
out << sep;
out << numbers[i]/normalization;
}
} else {
for(size_t i=0; i<numbers.size(); i++){
out << sep;
out << 0;
}
}
} else {
for(size_t i=0; i<numbers.size(); i++){
out << sep;
out << numbers[i];
}
}
out << std::endl;
}
}
}
void TQCutflowPlotter::writeTikZBody(std::ostream& out, TQTaggable& tags){
tags.importTags(this);
std::vector<TString> styles;
std::vector<TString> processnames;
std::vector<TString> processtitles;
TQTaggableIterator processes(this->fProcesses);
if(!processes.hasNext()){
WARNclass("no processes booked, writing empty cutflow plot!");
}
while(processes.hasNext()){
TQTaggable* process = processes.readNext();
if(process){
TString processPath, processName, processStyle, processTitle;
if(process->getTagString(".path",processPath)){
processPath = tags.replaceInText(processPath);
if(TQFolder::isValidPath(processPath,true,true,true)){
if(!process->getTagString(".name",processName)){
processName = TQFolder::makeValidIdentifier(processPath);
}
TList* folders = fReader->getListOfSampleFolders(processPath);
TQFolder* f = fReader->getSampleFolder()->findCommonBaseFolder(folders);
delete folders;
processStyle = "";
int color;
if(process->getTagInteger("histFillColor",color)||process->getTagInteger("color",color)||f->getTagInteger("~style.default.histFillColor",color)){
processStyle.Append("fill=");
TString colorName = processName;
colorName.Prepend("fill");
TString colordef = TQStringUtils::getColorDefStringLaTeX(colorName,color);
out << colordef << std::endl;
processStyle.Append(colorName);
}
if(process->getTagInteger("histLineColor",color)||process->getTagInteger("color",color)||f->getTagInteger("~style.default.histLineColor",color)){
if(color != kBlack){
if(!processStyle.IsNull()) processStyle.Append(",");
processStyle.Append("draw=");
TString colorName = processName;
colorName.Prepend("draw");
TString colordef = TQStringUtils::getColorDefStringLaTeX(colorName,color);
out << colordef << std::endl;
processStyle.Append(colorName);
}
}
process->getTagString(".style",processStyle);
if(f){
f->getTagString("~style.default.title",processTitle);
}
process->getTagString(".title",processTitle);
styles.push_back(processStyle);
processnames.push_back(processName);
processtitles.push_back(TQStringUtils::convertROOTTeX2LaTeX(processTitle));
}
}
}
}
out << "\\begin{tikzpicture}" << std::endl;
out << "\\pgfplotstableread[col sep=comma]{" << std::endl;
out << "label";
for(size_t i=0; i<processnames.size(); i++){
out << "," << "{" << processnames[i] << "}";
}
out << std::endl;
int nCuts = 0;
TQTaggableIterator cuts(this->fCuts);
while(cuts.hasNext()){
TQTaggable* cut = cuts.readNext();
if(!cut) continue;
TString cutTitle, cutName;
if(!cut->getTagString(".name",cutName)) continue;
if(!cut->getTagString(".title",cutTitle)) cutTitle=cutName;
if(cutName.BeginsWith("|")) continue;
cutTitle.ReplaceAll("_","");
out << "{" << cutTitle << "}";
nCuts++;
std::vector<double> numbers;
processes.reset();
while(processes.hasNext()){
TQTaggable* process = processes.readNext();
if(process){
TString processPath;
if(process->getTagString(".path",processPath)){
processPath = tags.replaceInText(processPath);
if(TQFolder::isValidPath(processPath,true,true,true)){
TQCounter * counter = fReader->getCounter(processPath, cutName,&tags);
if (counter) {
double number = counter->getCounter();
if(TQUtils::isNum(number)) numbers.push_back(number);
else numbers.push_back(0.);
delete counter;
} else {
numbers.push_back(0.);
}
}
}
}
}
if(tags.getTagBoolDefault("style.normalize",true)){
double normalization = 0.;
for(size_t i=0; i<numbers.size(); i++){
normalization += numbers[i];
}
if(normalization > 0){
for(size_t i=0; i<numbers.size(); i++){
out << ",";
out << "{" << numbers[i]/normalization << "}";
}
} else {
for(size_t i=0; i<numbers.size(); i++){
out << ",";
out << "{" << 0 << "}";
}
}
} else {
for(size_t i=0; i<numbers.size(); i++){
out << ",";
out << "{" << numbers[i] << "}";
}
}
out << std::endl;
}
out << "}\\datatable" << std::endl;
out << "\\begin{axis}[" << std::endl;
out << " height=" << nCuts << "*" << tags.getTagStringDefault("style.tikz.lineHeight","1.5em") << "," << std::endl;
out << " width=" << tags.getTagStringDefault("style.tikz.width","3cm") << "," << std::endl;
out << " scale only axis," << std::endl;
out << " enlarge y limits={abs=" << tags.getTagStringDefault("style.tikz.enlargeLimits","5pt") << "}," << std::endl;
out << " xmin=0," << std::endl;
out << " tick align=outside," << std::endl;
out << " axis x line*=bottom," << std::endl;
out << " axis y line*=left," << std::endl;
out << " legend cell align=left,legend style={draw=none,at={(1.10,0.5)},anchor=west}," << std::endl;
out << " every y tick/.style={draw=none}," << std::endl;
out << " xbar stacked, " << std::endl;
if(tags.getTagBoolDefault("style.tikz.reverseYordering",true)) out << " y dir=reverse," << std::endl;
if(tags.getTagBoolDefault("style.tikz.normalize",true)){
out << " scaled x ticks=false," << std::endl;
out << " x tick label style={/pgf/number format/fixed}," << std::endl;
out << " enlarge x limits=false," << std::endl;
} else {
out << " enlarge x limits=upper," << std::endl;
}
out << " bar width=" << tags.getTagStringDefault("style.tikz.barWidth","10pt") << "," << std::endl;
out << " ytick=data," << std::endl;
out << " yticklabels from table={\\datatable}{label}," << std::endl;
out << "]" << std::endl;
processes.reset();
size_t idx = 0;
while(processes.hasNext()){
TQTaggable* process = processes.readNext();
if(process){
TString processStyle, processName, processPath, processTitle;
if(process->getTagString(".path",processPath)){
processPath = tags.replaceInText(processPath);
if(TQFolder::isValidPath(processPath,true,true,true)){
if(!process->getTagString(".name",processName)){
processName = TQFolder::makeValidIdentifier(processPath);
}
out << "\\addplot[";
out << styles[idx];
out << "] table [x=" << processName << ", y expr=\\coordindex] {\\datatable};" << std::endl;
idx++;
}
}
}
}
if(tags.getTagBoolDefault("style.showLegend",false)){
bool mathtitles = tags.getTagBoolDefault("style.legendMathTitles",false);
out << "\\legend{";
for(size_t i=0; i<processtitles.size(); i++){
if(i!=0) out << ",";
if(mathtitles || ( (processtitles[i].Contains("\\") || processtitles[i].Contains("_") || processtitles[i].Contains("^")) && !processtitles[i].Contains("$")) ){
out << "\\ensuremath{" << processtitles[i] << "}";
} else {
out << processtitles[i];
}
}
out << "}" << std::endl;
}
out << "\\end{axis}" << std::endl;
out << "\\end{tikzpicture}%" << std::endl;
}
void TQCutflowPlotter::writeTikZFoot(std::ostream& out, TQTaggable& tags){
if(tags.getTagBoolDefault("standalone",true)){
out << "\\end{document}" << std::endl;
}
}
void TQCutflowPlotter::setup(){
}