Skip to content
2 changes: 2 additions & 0 deletions src/Applications/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set(
gundamConfigCompare
gundamPlotExtractor
gundamConfigUnfolder
gundamToysReader
)

set(SCRIPT_LIST
Expand Down Expand Up @@ -78,6 +79,7 @@ endforeach()
# Dependencies
target_link_libraries( gundamFitter GundamFitter )
target_link_libraries( gundamCalcXsec GundamFitter ) # using the fitter engine to parse back the config file
target_link_libraries( gundamToysReader GundamUtils )
target_link_libraries( gundamFitReader GundamUtils )
target_link_libraries( gundamInputZipper GundamUtils )
target_link_libraries( gundamFitCompare GundamUtils )
Expand Down
168 changes: 168 additions & 0 deletions src/Applications/src/gundamToysReader.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//
// Created by Nadrino on 14/02/2025.
//

#include "GundamApp.h"
#include "GundamGlobals.h"
#include "ConfigUtils.h"

#include "CmdLineParser.h"
#include "GenericToolbox.Time.h"
#include "GenericToolbox.Root.h"
#include "Logger.h"

#include "TChain.h"

#include <functional>
#include <ostream>
#include <memory>


std::unique_ptr<TChain> toysChain{nullptr};


void openInputFiles(const std::vector<std::string>& filesList_);
void drawHistogram(const JsonType& config_);


int main(int argc, char** argv){

GundamApp app{"toy reader"};

// --------------------------
// Read Command Line Args:
// --------------------------
CmdLineParser clParser;

clParser.getDescription() << "> gundamToysReader allows to summarize the fit results of multiple fits." << std::endl;
clParser.getDescription() << "> " << std::endl;
clParser.getDescription() << "> It takes a set of root files generated by gundamFitter and outputs plots." << std::endl;

clParser.addDummyOption("Input options");
clParser.addOption("input-files", {"-f", "--files"}, "Specify path to the fitter config file", -1);
clParser.addDummyOption();

clParser.addDummyOption("Debug options");
clParser.addOption("debugVerbose", {"--debug"}, "Enable debug verbose (can provide verbose level arg)", 1, true);


LogInfo << clParser.getDescription().str() << std::endl;

LogInfo << "Usage: " << std::endl;
LogInfo << clParser.getConfigSummary() << std::endl << std::endl;

clParser.parseCmdLine(argc, argv);

LogExitIf(clParser.isNoOptionTriggered(), "No option was provided.");

LogInfo << "Provided arguments: " << std::endl;
LogInfo << clParser.getValueSummary() << std::endl << std::endl;
LogInfo << clParser.dumpConfigAsJsonStr() << std::endl;

// --------------------------
// Init command line args:
// --------------------------
GundamGlobals::setIsDebug( clParser.isOptionTriggered("debugVerbose") );

// to write cmdLine info

// --------------------------------------------
// open input files ttrees
LogExitIf( not clParser.isOptionTriggered("input-files"), "input-files list not provided." );
openInputFiles( clParser.getOptionValList<std::string>("input-files") );


// --------------------------------------------
// open output file
std::string outFileName = "gundamToysReader";
// outFileName += "_" + GenericToolbox::getNowDateString("%Y%m%d_%H%M%S");
outFileName += ".root";

app.openOutputFile(outFileName);
app.setCmdLinePtr( &clParser );
app.writeAppInfo();

GenericToolbox::TFilePath out(app.getOutfilePtr(), "gundamToysReader");
out.getDir()->cd();
LogWarning << "Writing fit results..." << std::endl;
auto* outToyChain = toysChain->CloneTree(-1, "fast");
outToyChain->Write();



}

void openInputFiles(const std::vector<std::string>& filesList_){
gEnv->SetValue("TFile.Recover", 0);

// unfold the files list
std::vector<std::string> filePathList;
std::function<void(const std::vector<std::string>&)> unfoldFilePathList = [&](const std::vector<std::string>& inputFileList_){
for( auto& inputFile : inputFileList_ ){

if( GenericToolbox::endsWith(inputFile, ".root") ) {
filePathList.emplace_back(inputFile);
}
else if( GenericToolbox::endsWith(inputFile, ".txt") ){
unfoldFilePathList( GenericToolbox::dumpFileAsVectorString(inputFile) );
}
else{
LogError << "Invalid input file: " << inputFile << std::endl;
}

}
};
unfoldFilePathList(filesList_);

// sort files
auto aGoesFirst = [](const std::string& a_, const std::string& b_){
if( a_.empty() ) return false;
if( b_.empty() ) return true;

auto aSplit = GenericToolbox::splitString(a_, ".");
std::string aCut = aSplit[aSplit.size()-2];
if( GenericToolbox::doesStringEndsWithSubstring(aCut, "DryRun") ){
auto cutTrail = GenericToolbox::splitString(aCut, "_");
aCut = cutTrail[cutTrail.size() - 2];
}
else{ aCut = GenericToolbox::splitString(aCut, "_").back(); }

auto bSplit = GenericToolbox::splitString(b_, ".");
std::string bCut = bSplit[bSplit.size()-2];
if( GenericToolbox::doesStringEndsWithSubstring(bCut, "DryRun") ){
auto cutTrail = GenericToolbox::splitString(bCut, "_");
bCut = cutTrail[cutTrail.size() - 2];
}
else{ bCut = GenericToolbox::splitString(bCut, "_").back(); }

try{ return std::stoi(aCut) < std::stoi(bCut); }
catch (...){} // if one of the two aren't convertible to in
return false;
};
std::sort(filePathList.begin(), filePathList.end(), aGoesFirst);


if( toysChain == nullptr ) {
toysChain = std::make_unique<TChain>("FitterEngine/postFit/bestFitStats");
}

for( auto& file : filePathList ){

auto fTemp = std::shared_ptr<TFile>(TFile::Open(file.c_str()));
LogContinueIf( fTemp == nullptr, "Could not open: " << file);
LogContinueIf( fTemp->Get("FitterEngine/postFit/bestFitStats") == nullptr, "Could not find: FitterEngine/postFit/bestFitStats in " << file);
fTemp->Close();

LogInfo << "Adding "<< file << std::endl;
toysChain->AddFile(file.c_str());
}
LogExitIf(toysChain->GetEntries() == 0, "No input file opened.");
LogInfo << "Loaded " << toysChain->GetEntries() << " toy files." << std::endl;


}
void drawHistogram(const JsonType& config_){



}