diff --git a/core/qa/checker/CbmQaCheckerCore.cxx b/core/qa/checker/CbmQaCheckerCore.cxx index 546d7bb68a42cfbc43c68ac093c683081711620f..3125a699e16c26bf7a29f762359ca849c8209fc1 100644 --- a/core/qa/checker/CbmQaCheckerCore.cxx +++ b/core/qa/checker/CbmQaCheckerCore.cxx @@ -13,7 +13,6 @@ #include "Logger.h" #include "TClonesArray.h" #include "TFile.h" -#include "TFolder.h" //#include <boost/filesystem.hpp> #include <regex> @@ -40,7 +39,7 @@ void Core::AddDataset(const char* dataset) { fpObjDB->AddDataset(dataset); } void Core::RegisterOutFile(const char* filename) { LOG(info) << "Core: Registering output file: " << filename; - fpOutFile = std::make_unique<TFile>(filename, "RECREATE"); + fpObjDB->SetOutputPath(filename); } // --------------------------------------------------------------------------------------------------------------------- @@ -50,27 +49,15 @@ void Core::Process(Option_t* opt) // ----- Init the object database fpObjDB->Init(); - // ----- Register output file - if (fpOutFile == nullptr) { - this->RegisterOutFile("QaCheckerOutput.root"); - } + PrepareOutputFile(); // ----- Process datasets and files int nDatasets = fpObjDB->GetNofDatasets(); - std::vector<TFolder*> vDSFolders(nDatasets, nullptr); - for (int iDS = 0; iDS < nDatasets; ++iDS) { - // Create a new folder for dataset (/dataset) - auto* pDSDir = fpOutFile->mkdir(fpObjDB->GetDataset(iDS).data()); - - // Loop over files for (int iFile = 0; iFile < fpObjDB->GetNofFiles(); ++iFile) { - // Define output folder for file (/dataset/file) - auto* pFileDir = pDSDir->mkdir(fpObjDB->GetFileLabel(iFile).data()); - // Create and process a file handler - auto pFileHandler = std::make_unique<FileHandler>(fpObjDB, pFileDir, iDS, iFile); + auto pFileHandler = std::make_unique<FileHandler>(fpObjDB, iDS, iFile); pFileHandler->Process(opt); } // iFile } // iDS @@ -80,6 +67,20 @@ void Core::Process(Option_t* opt) // void Core::SetFromYAML(const char* configName) { fpObjDB->ReadFromYAML(configName); } +// --------------------------------------------------------------------------------------------------------------------- +// +void Core::PrepareOutputFile() +{ + TFile outFile(fpObjDB->GetOutputPath().c_str(), "RECREATE"); + for (int iDS = 0; iDS < fpObjDB->GetNofDatasets(); ++iDS) { + auto* pDSDir = outFile.mkdir(fpObjDB->GetDataset(iDS).c_str()); + for (int iFile = 0; iFile < fpObjDB->GetNofFiles(); ++iFile) { + pDSDir->mkdir(fpObjDB->GetFileLabel(iFile).c_str()); + } + } + outFile.Close(); +} + // --------------------------------------------------------------------------------------------------------------------- // bool Core::Scan() const diff --git a/core/qa/checker/CbmQaCheckerCore.h b/core/qa/checker/CbmQaCheckerCore.h index 5390e4f3873028d04c382dd2e41d8d0a91000d32..7dae9e67d0973ddd6ac455b48bcf5ed3118b408e 100644 --- a/core/qa/checker/CbmQaCheckerCore.h +++ b/core/qa/checker/CbmQaCheckerCore.h @@ -98,7 +98,10 @@ namespace cbm::qa::checker void SetInputRootPath(const char* pathName) { fpObjDB->SetInputRootPath(pathName); } private: - std::shared_ptr<TFile> fpOutFile = nullptr; ///< Output file + /// @brief Prepares output file (creates directory structure) + void PrepareOutputFile(); + + std::shared_ptr<ObjectDB> fpObjDB = nullptr; ///< Database of names FlagBitSet_t fControlBits; ///< Control bit flags diff --git a/core/qa/checker/CbmQaCheckerFileHandler.cxx b/core/qa/checker/CbmQaCheckerFileHandler.cxx index dd799211d56a2395b822b713981acd23cd7c7908..a1517d6fbb1640bd16a8b8fda9ff33667c9af2c3 100644 --- a/core/qa/checker/CbmQaCheckerFileHandler.cxx +++ b/core/qa/checker/CbmQaCheckerFileHandler.cxx @@ -34,12 +34,12 @@ using cbm::qa::checker::FileHandler; // --------------------------------------------------------------------------------------------------------------------- // -FileHandler::FileHandler(std::shared_ptr<ObjectDB>& pObjDB, TDirectory* pOutDir, int iDataset, int iFile) +FileHandler::FileHandler(std::shared_ptr<ObjectDB>& pObjDB, int iDataset, int iFile) : fFileID(iFile) , fDatasetID(iDataset) , fpObjDB(pObjDB) - , fpOutDir(pOutDir) { + ReOpenOutputFile(); fpInputFiles = std::make_unique<TClonesArray>("TFile"); for (int iVer = 0; iVer < fpObjDB->GetNofVersions(); ++iVer) { @@ -63,6 +63,8 @@ FileHandler::~FileHandler() // ----- Clean pointers fpInputFiles->Delete(); fpInputFiles = nullptr; + fpOutputFile->Close(); + fpOutputFile = nullptr; } // --------------------------------------------------------------------------------------------------------------------- @@ -114,8 +116,12 @@ void FileHandler::Process(Option_t* opt) } // Create an instance of an object handler + if (iObj != 0 && (20 * iObj) % nObjects == 0) { + ReOpenOutputFile(); + LOG(info) << "FileHandler: processing object " << iObj << " of " << nObjects; + } std::unique_ptr<ObjectHandler> pObjHandler = nullptr; - //LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"'; + LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"'; if (dynamic_cast<TH2*>(vpObjects[0])) { pObjHandler = std::make_unique<Hist2DHandler>(iObj, fFileID, fDatasetID); if (bCmpPointByPoint) { @@ -170,6 +176,7 @@ void FileHandler::Process(Option_t* opt) } } pObjHandler->Write(); + gFile->Flush(); // Clean memory for (auto* pObj : vpObjects) { @@ -178,6 +185,19 @@ void FileHandler::Process(Option_t* opt) pObj = nullptr; } } - } // iObj } + +// --------------------------------------------------------------------------------------------------------------------- +// +void FileHandler::ReOpenOutputFile() +{ + if (fpOutputFile.get()) { + fpOutputFile->Close(); + fpOutputFile = nullptr; + fpOutDir = nullptr; + } + fpOutputFile = std::make_unique<TFile>(fpObjDB->GetOutputPath().c_str(), "UPDATE"); + TString dirName = fpObjDB->GetDataset(fDatasetID) + "/" + fpObjDB->GetFileLabel(fFileID); + fpOutDir = fpOutputFile->Get<TDirectory>(dirName); +} diff --git a/core/qa/checker/CbmQaCheckerFileHandler.h b/core/qa/checker/CbmQaCheckerFileHandler.h index 580fae408f8a6ea57c1dd490e5632645719b67b4..c8128b0f2ced4c4ceeffce721dafdea78d0a5011 100644 --- a/core/qa/checker/CbmQaCheckerFileHandler.h +++ b/core/qa/checker/CbmQaCheckerFileHandler.h @@ -29,10 +29,9 @@ namespace cbm::qa::checker public: /// @brief Constructor /// @param pObjDB Shared pointer to object database - /// @param pOutDir Directory to store the output (/dataset/file) /// @param iDataset Index of dataset /// @param iFile Index of file - FileHandler(std::shared_ptr<ObjectDB>& pObjDB, TDirectory* pOutDir, int iDataset, int iFile); + FileHandler(std::shared_ptr<ObjectDB>& pObjDB, int iDataset, int iFile); /// @brief Destructor ~FileHandler(); @@ -71,12 +70,16 @@ namespace cbm::qa::checker /// @return Pointer to created TDirectory object TDirectory* CreateNestedDirectory(const std::string& path); + /// @brief Closes and opens output file + void ReOpenOutputFile(); + int fFileID = -1; ///< Index of file int fDatasetID = -1; ///< Index of dataset std::shared_ptr<ObjectDB> fpObjDB = nullptr; ///< Pointer to object database TDirectory* fpOutDir = nullptr; ///< Pointer to output directory std::unique_ptr<TClonesArray> fpInputFiles = nullptr; ///< Pointer to input files array + std::unique_ptr<TFile> fpOutputFile = nullptr; ///< Pointer to output file // TODO: replace fpOutputFolder with shared_ptr }; diff --git a/core/qa/checker/CbmQaCheckerObjectDB.cxx b/core/qa/checker/CbmQaCheckerObjectDB.cxx index 44f4ed3d9dce445863b693d0be135350e2146232..87853e20d7aad87af91dfb3e5e31f14e74ac902e 100644 --- a/core/qa/checker/CbmQaCheckerObjectDB.cxx +++ b/core/qa/checker/CbmQaCheckerObjectDB.cxx @@ -71,6 +71,11 @@ void ObjectDB::Init() << GetNofVersions() << " were provided)"; + // ----- Define output file + if (fsOutputPath.empty()) { + fsOutputPath = "QaCheckerOutput.root"; + } + // ----- Define default version index if (fsDefaultLabel.size()) { auto it = std::find(fvVersionLabels.cbegin(), fvVersionLabels.cend(), fsDefaultLabel); @@ -249,7 +254,7 @@ void ObjectDB::ReadObjectList(int iFile) std::set<std::string> objectPaths; LOG(info) << "Reading object list from files: ..."; for (int iDs = 0; iDs < static_cast<int>(fvDatasets.size()); ++iDs) { - const char* fileName = this->GetInputFileName(fDefVersionID, iFile, iDs).c_str(); + TString fileName = this->GetInputFileName(fDefVersionID, iFile, iDs); LOG(info) << "- file: " << fileName; TFile fileIn{fileName, "READONLY"}; fileIn.cd(); diff --git a/core/qa/checker/CbmQaCheckerObjectDB.h b/core/qa/checker/CbmQaCheckerObjectDB.h index dc73e1e4fdfea5400886bdd95f406d7dc9d37e2c..ffb3d01706367741f6f5b3615eeca2f7c32208b1 100644 --- a/core/qa/checker/CbmQaCheckerObjectDB.h +++ b/core/qa/checker/CbmQaCheckerObjectDB.h @@ -122,6 +122,9 @@ namespace cbm::qa::checker /// @brief Gets number of versions int GetNofVersions() const { return fvVersionLabels.size(); } + /// @brief Gets output path + const std::string& GetOutputPath() const { return fsOutputPath; } + /// @brief Gets version label /// @param iVersion Index of version const std::string& GetVersionLabel(int iVersion) const { return fvVersionLabels[iVersion]; } @@ -165,6 +168,10 @@ namespace cbm::qa::checker /// @param pathName Relative or absolute root path to input the input directories void SetInputRootPath(const char* pathName) { fsInputRootPath = pathName; } + /// @brief Sets the output path + /// @param path Path to the output ROOT-file + void SetOutputPath(const char* path) { fsOutputPath = path; } + private: /// @brief Reads list of histograms from file /// @param iFile Index of file @@ -180,6 +187,7 @@ namespace cbm::qa::checker int fDefVersionID = -1; ///< Index of default version std::string fsInputRootPath = ""; ///< Root path for input files + std::string fsOutputPath = ""; ///< Path to the output file std::string fsDefaultLabel = ""; ///< Name of default version label std::vector<std::string> fvDatasets; ///< Container of dataset names diff --git a/macro/qa/qa_compare_ca.C b/macro/qa/qa_compare_ca.C index 04541db7dc94d654d88c9dc6972679d2dd95aef6..ddb750158a839df51c2040e3433076b142bfa2e9 100644 --- a/macro/qa/qa_compare_ca.C +++ b/macro/qa/qa_compare_ca.C @@ -36,7 +36,7 @@ int qa_compare_ca( pQaChecker->SetFromYAML(configName); // Read file-object map //// ----- Run comparision routine - pQaChecker->Process("PRB"); // P - + pQaChecker->Process("PRC"); // P - //// ----- Scan results bool res = pQaChecker->Scan(); // true - objects are the same, false - objects differ