#include "QFramework/TQSampleVisitor.h"
#include "QFramework/TQSampleFolder.h"
#include "QFramework/TQFolder.h"
#include "QFramework/TQSample.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQToken.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQStringUtils.h"
#include "QFramework/TQLibrary.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
ClassImp(TQSampleVisitor)
TString TQSampleVisitor::statusSKIPPED(bool pretty){ if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldPink ("SKIP")+TQStringUtils::makeBoldWhite(" ]"); else return "[ SKIP ]";}
TString TQSampleVisitor::statusOK(bool pretty){ if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldGreen (" OK ")+TQStringUtils::makeBoldWhite(" ]"); else return "[ OK ]";}
TString TQSampleVisitor::statusFAILED(bool pretty){ if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldRed ("FAIL")+TQStringUtils::makeBoldWhite(" ]"); else return "[ FAIL ]";}
TString TQSampleVisitor::statusWARN(bool pretty){ if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldYellow("WARN")+TQStringUtils::makeBoldWhite(" ]"); else return "[ WARN ]";}
TString TQSampleVisitor::statusSKIPPEDOK(bool pretty){ if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldGreen ("SKIP")+TQStringUtils::makeBoldWhite(" ]"); else return "[ SKIP ]";}
TString TQSampleVisitor::statusRUNNING(bool pretty){ if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldWhite ("....")+TQStringUtils::makeBoldWhite(" ]"); else return "[ .... ]";}
TString TQSampleVisitor::statusPROGRESS(bool pretty, double fraction) { if(pretty) return TQStringUtils::makeBoldWhite("[ ")+TQStringUtils::makeBoldWhite (TQStringUtils::fixedWidth(TString::Format("%.0f%%",fraction*100.),4,'c') )+TQStringUtils::makeBoldWhite(" ]"); else return TString("[ ")+ (TQStringUtils::fixedWidth(TString::Format("%.0f%%",fraction*100.),4,'c') )+ (" ]");}
TQSampleVisitor::TQSampleVisitor(const TString& name) :
TNamed(name,name),
fSampleColWidth(0.45*TQLibrary::getConsoleWidth()),
fVerbose(false),
fPrettyPrint(true),
fUpdateLines(true)
{
fVisitTraceID.Clear();
}
void TQSampleVisitor::setVerbose(bool verbose) {
fVerbose = verbose;
}
void TQSampleVisitor::setPrettyPrint(bool pretty) {
fPrettyPrint = pretty;
}
void TQSampleVisitor::setLineUpdates(bool allow) {
fUpdateLines = allow;
}
bool TQSampleVisitor::setVisitTraceID(TString id) {
if (id.IsNull()) {
fVisitTraceID.Clear();
return true;
} else if (TQSampleFolder::isValidName(id)) {
fVisitTraceID = id;
return true;
} else {
return false;
}
}
TString TQSampleVisitor::getVisitTraceID() const {
return fVisitTraceID;
}
const char* TQSampleVisitor::getVisitTraceIDConst() const {
return fVisitTraceID.Data();
}
TString TQSampleVisitor::getStatusString(int status, bool pretty, double progress) {
if (status == visitSKIPPED) return TQSampleVisitor::statusSKIPPED(pretty);
if (status == visitOK) return TQSampleVisitor::statusOK(pretty);
if (status == visitFAILED) return TQSampleVisitor::statusFAILED(pretty);
if (status == visitWARN) return TQSampleVisitor::statusWARN(pretty);
if (status == visitSKIPPEDOK) return TQSampleVisitor::statusSKIPPEDOK(pretty);
if (status == visitPROGRESS) return TQSampleVisitor::statusPROGRESS(pretty,progress);
return "";
}
bool TQSampleVisitor::callInitialize(TQSampleFolder * sampleFolder) {
if (fVerbose) {
int width = 50;
std::cout << std::endl;
std::cout << TQStringUtils::repeat('-', width) << std::endl;
if(fPrettyPrint) std::cout << TQStringUtils::makeBoldWhite("Initializing...") << std::endl;
else std::cout << "Initializing..." << std::endl;
std::cout << TString::Format("%-20s: %s", "Visitor", ClassName()) << std::endl;
std::cout << TString::Format("%-20s: %s", "Sample Folder",
sampleFolder->getPath().Data()) << std::endl;
std::cout << TQStringUtils::repeat('-', width) << std::endl;
std::cout << std::endl << std::endl;
}
TString message;
int result = initialize(sampleFolder, message);
if (fVerbose && fPrettyPrint) {
std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth("Sample",fSampleColWidth));
std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::fixedWidth("Status",8,"c"));
std::cout << " ";
std::cout << TQStringUtils::makeBoldWhite(message);
std::cout << std::endl;
std::cout << TQStringUtils::makeBoldWhite(TQStringUtils::repeat("=", TQLibrary::getConsoleWidth())) << std::endl;
} else if(fVerbose){
std::cout << (TQStringUtils::fixedWidth("Sample",fSampleColWidth));
std::cout << (TQStringUtils::fixedWidth("Status",8,"c"));
std::cout << " ";
std::cout << (message);
std::cout << std::endl;
std::cout << (TQStringUtils::repeat("=", TQLibrary::getConsoleWidth())) << std::endl;
}
return (result != visitFAILED);
}
int TQSampleVisitor::initialize(TQSampleFolder * , TString& message) {
message.Append(TQStringUtils::fixedWidth("Info", 30));
return visitOK;
}
TString TQSampleVisitor::printLine(TQSampleFolder* f, int level, bool isSample, const TString& bullet){
TString line = TString::Format("%*s%s ", level*2, "", bullet.Data());
if (isSample) {
line += f->getNameConst();
} else {
if(fPrettyPrint){
line += TQStringUtils::makeBoldBlue(f->getNameConst());
} else {
line += (f->getNameConst());
}
}
if(fUpdateLines || !isSample){
std::cout << TQStringUtils::fixedWidth(line, fSampleColWidth, "l");
if(isSample){
std::cout << TQSampleVisitor::statusRUNNING(fPrettyPrint);
std::cout << "\r";
std::cout.flush();
} else {
std::cout << std::endl;
}
}
return line;
}
void TQSampleVisitor::updateLine(const TString& line, const TString& message, int result, bool ignore, double progress){
if(ignore){
if (result != visitPROGRESS) std::cout << std::endl;
return;
} else {
if (result == visitSKIPPED || result == visitOK || result == visitWARN || result == visitFAILED || result == visitSKIPPEDOK) {
std::cout << TQStringUtils::fixedWidth(line, fSampleColWidth, "l") << this->getStatusString(result,fPrettyPrint) << " " << TQStringUtils::rtrim(message) << std::endl;
} else if (result == visitLISTONLY) {
std::cout << TQStringUtils::fixedWidth(line, fSampleColWidth, "l") << std::endl;
} else if (result == visitIGNORE) {
std::cout << TQStringUtils::fixedWidth(line, fSampleColWidth, "l") << std::endl;
} else if (fUpdateLines && result == visitPROGRESS) {
std::cout << TQStringUtils::fixedWidth(line, fSampleColWidth, "l") << this->getStatusString(result,fPrettyPrint,progress) << " " << message << "\r";
std::cout.flush();
}
}
}
int TQSampleVisitor::visit(TQSampleFolder * sampleFolder, bool requireSelectionTag) {
if(!sampleFolder) return 0;
int nVisits = 0;
try {
this->callInitialize(sampleFolder);
nVisits = this->callVisit(sampleFolder,0,requireSelectionTag);
this->callFinalize();
} catch (const std::bad_alloc& oom){
Long64_t vsize = TQLibrary::getVirtualMemory();
TQLibrary::recordMemory();
if(vsize > 0){
ERRORclass("machine ran out of memory while visiting sample folder '%s', current memory usage is %.3f MB",sampleFolder->getPath().Data(),vsize);
} else {
ERRORclass("machine ran out of memory while visiting sample folder '%s' and unable to retrieve current memory usage (sorry!)",sampleFolder->getPath().Data());
}
nVisits=-1;
}
return nVisits;
}
void TQSampleVisitor::leaveTrace(TQSampleFolder* sampleFolder, TString prefix, int result, const TString& message){
TString resultStr = this->getStatusString(result,false);
prefix.Append(this->getVisitTraceIDConst());
if(!message.IsNull()){
DEBUGclass("writing message");
sampleFolder->setTagString(prefix+".message", TQStringUtils::compactify(message));
}
sampleFolder->setTagInteger(prefix + ".statusID", result);
if(!resultStr.IsNull())
sampleFolder->setTagString(prefix + ".status", resultStr);
}
int TQSampleVisitor::getStatusID(TQSampleFolder* sampleFolder, TString prefix){
prefix.Append(this->getVisitTraceIDConst());
return sampleFolder->getTagIntegerDefault(prefix + ".statusID", -1);
}
bool TQSampleVisitor::checkRestrictionTag(TQSampleFolder* sf) {
if (!sf) return false;
return (sf->getTagBoolDefault(TString("~")+TQSampleFolder::restrictSelectionTagName, false) ||
sf->getTagBoolDefault(TQSampleFolder::restrictSelectionTagName+TString("~"), false));
}
int TQSampleVisitor::callVisit(TQSampleFolder * sampleFolder, int level, bool requireSelectionTag) {
if (!sampleFolder) return 0;
if (requireSelectionTag) {
DEBUGclassargs(this->GetName(),"Checking selection tag requirement for TQSampleFolder '%s'",sampleFolder->GetName());
if (! TQSampleVisitor::checkRestrictionTag(sampleFolder) ) {
DEBUGclassargs(this->GetName(),"Skipping sample folder '%s' as it doesn't seem to be selected",sampleFolder->GetName());
return 0;
}
}
TQSample* sample = dynamic_cast<TQSample*>(sampleFolder);
bool isSample = (bool)(sample) && (!sample->hasSubSamples());
if (sampleFolder->hasTagString("asv.initialize.dumpTopTo")) {
TQUtils::dumpTop(sampleFolder->getTagStringDefault("asv.initialize.dumpTopTo",".") , TString::Format("%ld_initialize_%s",TQUtils::getCurrentTime(),sampleFolder->getName().Data()) , TString::Format("%s\n-----------------------------\n",sampleFolder->getPath().Data()));
}
TQLibrary::recordMemory();
int result;
int nVisits = 0;
TString message;
if (isSample) {
DEBUGclassargs(this->GetName(),"visiting as sample");
if (fVerbose) fStatusLine = this->printLine(sampleFolder,level,true,"+");
result = visitSample(sample, message);
nVisits += (result == visitOK);
this->leaveTrace(sampleFolder,".sv.visit.",result,message);
if (fVerbose) this->updateLine(fStatusLine,message,result);
DEBUGclassargs(this->GetName(),"revisiting as sample");
result = revisitSample(sample, message);
this->leaveTrace(sampleFolder,".sv.revisit.",result,message);
} else {
DEBUGclassargs(this->GetName(),"visiting as folder");
if (fVerbose) fStatusLine = this->printLine(sampleFolder,level,false,"+");
result = visitFolder(sampleFolder, message);
this->leaveTrace(sampleFolder,".sv.visit.",result,message);
if(result != visitFAILED && result != visitSKIPPED && result != visitSKIPPEDOK){
TQSampleFolderIterator itr(sampleFolder->getListOfSampleFolders("?"),true);
while (itr.hasNext()) {
TQSampleFolder * element = itr.readNext();
if (element){
nVisits += this->callVisit(element, level + 1, requireSelectionTag);
}
}
}
DEBUGclassargs(this->GetName(),"revisiting as folder");
if (fVerbose) fStatusLine = this->printLine(sampleFolder,level,false,"-");
result = revisitFolder(sampleFolder, message);
this->leaveTrace(sampleFolder,".sv.revisit.",result,message);
}
if (sampleFolder->hasTagString("sv.finalize.dumpTopTo")) {
TQUtils::dumpTop(sampleFolder->getTagStringDefault("sv.finalize.dumpTopTo",".") , TString::Format("%ld_finalize_%s",TQUtils::getCurrentTime(),sampleFolder->getName().Data()) , TString::Format("%s\n-----------------------------\n",sampleFolder->getPath().Data()));
}
TQLibrary::recordMemory();
return (result == visitOK || result == visitWARN || result == visitIGNORE || result == visitLISTONLY) ? nVisits : 0;
}
int TQSampleVisitor::visitFolder(TQSampleFolder * sampleFolder, TString& ) {
(void)sampleFolder;
DEBUGclassargs(this->GetName(),"Visiting folder '%s'", sampleFolder? sampleFolder->getPath().Data() : "");
return visitLISTONLY;
}
int TQSampleVisitor::visitSample(TQSample * sample, TString& message) {
DEBUGclassargs(this->GetName(),"Entering function");
if (!sample) return visitFAILED;
int result = visitFAILED;
int nEntries = -1;
TString msg = "";
TQToken * treeToken = sample->getTreeToken();
if (treeToken) {
result = visitOK;
nEntries = ((TTree*)treeToken->getContent())->GetEntries();
sample->returnTreeToken(treeToken);
} else {
result = visitFAILED;
msg = "failed to load tree";
}
message.Append(" ");
TString treeLocation = sample->getTreeLocation();
if (treeLocation.Length() > 40) {
if (treeLocation.Length() > 43) {
treeLocation.Remove(0, treeLocation.Length() - 37);
treeLocation.Prepend("...");
} else {
treeLocation.Remove(0, treeLocation.Length() - 40);
}
}
message.Append(TQStringUtils::fixedWidth(treeLocation, 40, true));
int nEventsBin;
if (sample->getTagInteger(".init.neventsbin", nEventsBin)) {
message.Append(TQStringUtils::fixedWidth(TString::Format("%d", nEventsBin), 12)); }
else {
message.Append(TQStringUtils::fixedWidth("--", 12)); }
if (nEntries >= 0) {
message.Append(TQStringUtils::fixedWidth(TString::Format("%d", nEntries), 12)); }
else {
message.Append(TQStringUtils::fixedWidth("--", 12)); }
message.Append(TQStringUtils::fixedWidth(TString::Format("%.3f", sample->getNormalisation()), 12));
double xSec;
if (sample->getTagDouble("xsection", xSec)) {
message.Append(TQStringUtils::fixedWidth(TString::Format("%.3f", xSec), 12)); }
else {
message.Append(TQStringUtils::fixedWidth("--", 12)); }
double kFactor;
if (sample->getTagDouble("kfactor", kFactor)) {
message.Append(TQStringUtils::fixedWidth(TString::Format("%.3f", kFactor), 12)); }
else {
message.Append(TQStringUtils::fixedWidth("--", 12)); }
message.Append(TQStringUtils::fixedWidth(msg, 30));
return result;
}
int TQSampleVisitor::revisitSample(TQSample * , TString& ) {
return visitIGNORE;
}
int TQSampleVisitor::revisitFolder(TQSampleFolder * , TString& ) {
return visitIGNORE;
}
bool TQSampleVisitor::callFinalize() {
int result = finalize();
return (result != visitFAILED);
}
int TQSampleVisitor::finalize() {
return visitLISTONLY;
}
TQSampleVisitor::~TQSampleVisitor() {
}
void TQSampleVisitor::stamp(TQTaggable* obj) const {
obj->setTagInteger(TString::Format(".%s.timestamp.machine",this->getVisitTraceIDConst()),TQUtils::getCurrentTime());
obj->setTagString(TString::Format(".%s.timestamp.human",this->getVisitTraceIDConst()),TQUtils::getTimeStamp());
obj->setTagBool(TString::Format(".%s.visited",this->getVisitTraceIDConst()),true);
}
void TQSampleVisitor::unstamp(TQTaggable* obj) const {
obj->removeTag(TString::Format(".%s.timestamp.machine",this->getVisitTraceIDConst()));
obj->removeTag(TString::Format(".%s.timestamp.human",this->getVisitTraceIDConst()));
obj->removeTag(TString::Format(".%s.visited",this->getVisitTraceIDConst()));
}
bool TQSampleVisitor::checkVisit(TQTaggable* obj) const {
return obj ? obj->getTagBoolDefault(TString::Format(".%s.visited",this->getVisitTraceIDConst()),false) : false;
}
bool TQSampleVisitor::checkVisitFriends(TQSampleFolder* obj) const {
if (!obj) {
ERRORfunc("SampleFolder provided is a Null pointer!");
return false;
}
updateFriends(obj);
std::shared_ptr<std::set<TQSampleFolder*>> friends = obj->getFriends();
if (!friends) {
throw std::runtime_error( TString::Format("Could not obtain set of Friend SampleFolders (got Null pointer) for SF at path '%s'",obj->getPath().Data() ).Data() );
}
for (auto sf : (*friends)) {
if (!sf) continue;
if (!this->checkVisit(sf)) {
DEBUGfunc("SampleFolder '%s' has not been visited yet!",sf->getPath().Data());
return false;
}
}
DEBUGfunc("SampleFolder '%s' has already been visited yet!",obj->getPath().Data());
return true;
}
void TQSampleVisitor::updateFriends(TQSampleFolder* sf) {
if (!sf) return;
if (sf->countFriends() > 0) {DEBUGclass("Already has friends..."); return;}
sf->findFriends();
return;
}