CbmRoot
Loading...
Searching...
No Matches
CbmQaCheckerFileHandler.cxx
Go to the documentation of this file.
1/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
11
15#include "Logger.h"
16#include "TDirectoryFile.h"
17#include "TFile.h"
18#include "TFolder.h"
19#include "TH1.h"
20#include "TH2.h"
21#include "TNamed.h"
22#include "TProfile.h"
23#include "TROOT.h"
24
25#include <boost/algorithm/string.hpp>
26
27#include <cstdlib>
28#include <iomanip>
29#include <sstream>
30#include <string>
31
32
35
36// ---------------------------------------------------------------------------------------------------------------------
37//
38FileHandler::FileHandler(std::shared_ptr<ObjectDB>& pObjDB, int iDataset, int iFile)
39 : fFileID(iFile)
40 , fDatasetID(iDataset)
41 , fpObjDB(pObjDB)
42{
44 fpInputFiles = std::make_unique<TClonesArray>("TFile");
45
46 for (int iVer = 0; iVer < fpObjDB->GetNofVersions(); ++iVer) {
47 std::string filename = fpObjDB->GetInputFileName(iVer, fFileID, fDatasetID);
48 auto* pInFile = new ((*fpInputFiles)[iVer]) TFile(filename.data(), "READONLY");
49 LOG(info) << "File: " << pInFile->GetName();
50 LOG_IF(fatal, !pInFile->IsOpen()) << "FileHandler: file " << filename << " cannot be opened";
51 }
52
53 // Check registered folder
54 LOG_IF(fatal, !fpObjDB.get()) << "FileHandler: attempt to register a null pointer for the object database";
55 LOG_IF(fatal, !fpOutDir) << "FileHandler: attempt to register a null pointer for the output directory";
56 LOG_IF(fatal, fDatasetID < 0) << "FileHandler: attempt to register undefined dataset index";
57 LOG_IF(fatal, fFileID < 0) << "FileHandler: attempt to register undefined file index";
58}
59
60// ---------------------------------------------------------------------------------------------------------------------
61//
63{
64 // ----- Clean pointers
65 fpInputFiles->Delete();
66 fpInputFiles = nullptr;
67 fpOutputFile->Close();
68 fpOutputFile = nullptr;
69}
70
71// ---------------------------------------------------------------------------------------------------------------------
72//
73TDirectory* FileHandler::CreateNestedDirectory(const std::string& path)
74{
75 fpOutDir->mkdir(path.data());
76 return fpOutDir->GetDirectory(path.data());
77}
78
79// ---------------------------------------------------------------------------------------------------------------------
80//
81std::vector<ECmpInference> FileHandler::Process(Option_t* opt)
82{
83 std::vector<ECmpInference> bCmpResult;
84 int nObjects = fpObjDB->GetNofObjects(fFileID);
85 int nVersions = fpObjDB->GetNofVersions();
86 bCmpResult.resize(nVersions, ECmpInference::StronglyEqual);
87
88 // ----- Initial checks
89 if (!nObjects) {
90 LOG(warn) << "FileHandler: No objects were passed to file \"" << nObjects << ". Skipping file";
91 return bCmpResult;
92 }
93
94 // ----- Option parsing
95 std::string sOption = opt;
96 for (auto& ch : sOption) {
97 ch = std::tolower(ch);
98 }
99 bool bSuppressCanvases = sOption.find("b") != std::string::npos;
100 bool bForceCanvases = sOption.find("c") != std::string::npos;
101 bool bCmpExact = sOption.find("e") != std::string::npos;
102 bool bCmpChi2 = sOption.find("s") != std::string::npos;
103 bool bCmpRatio = sOption.find("u") != std::string::npos;
104
105 LOG(info) << "FileHandler: processing objects: ...";
106 std::vector<TNamed*> vpObjects(nVersions, nullptr); // vector to keep object different versions
107 for (int iObj = 0; iObj < nObjects; ++iObj) {
108 bool skipObj = false;
109 for (int iVer = 0; iVer < nVersions; ++iVer) {
110 auto* pInputFile = static_cast<TFile*>(fpInputFiles->At(iVer));
111 vpObjects[iVer] = pInputFile->Get<TNamed>(fpObjDB->GetObject(fFileID, iObj).c_str());
112 if (!vpObjects[iVer]) {
113 //LOG(warn) << "FileHandler: object " << fpObjDB->GetObject(fFileID, iObj) << " is undefined for version "
114 // << fpObjDB->GetVersionLabel(iVer) << ". This object will be skipped";
115 skipObj = true;
116 }
117 } // iVer
118 if (skipObj) {
119 continue;
120 }
121
122 //
123 if (iObj != 0 && nObjects % 500 == 0) {
125 LOG(info) << "FileHandler: object " << iObj << " / " << nObjects;
126 }
127
128 // Create an instance of an object handler
129 std::unique_ptr<ObjectHandler> pObjHandler = nullptr;
130 //LOG(info) << "FileHandler: processing object \"" << vpObjects[0]->GetName() << '\"';
131 if (dynamic_cast<TProfile*>(vpObjects[0])) {
132 pObjHandler = std::make_unique<Profile1DHandler>(iObj, fFileID, fDatasetID);
133 }
134 else if (dynamic_cast<TH2*>(vpObjects[0])) {
135 pObjHandler = std::make_unique<Hist2DHandler>(iObj, fFileID, fDatasetID);
136 }
137 else if (dynamic_cast<TH1*>(vpObjects[0])) {
138 pObjHandler = std::make_unique<Hist1DHandler>(iObj, fFileID, fDatasetID);
139 }
140 else {
141 LOG(warn) << "FileHandler: Object " << fpObjDB->GetObject(fFileID, iObj) << " has a type \""
142 << vpObjects[0]->ClassName()
143 << "\", which is unknown to the cbm::qa::checker framework, it will be skipped";
144 continue;
145 }
146 if (bCmpExact) {
147 pObjHandler->SetComparisonMethod(ECmpMethod::Exact); // Compare point-by-point (exact equality)
148 }
149 if (bCmpChi2) {
150 pObjHandler->SetComparisonMethod(ECmpMethod::Chi2); // Compare with chi2 test
151 }
152 if (bCmpRatio) {
153 pObjHandler->SetComparisonMethod(ECmpMethod::Ratio);
154 }
155 pObjHandler->SetObjectDB(fpObjDB);
156 pObjHandler->SetOutputDirectory(CreateNestedDirectory((fpObjDB->GetObject(fFileID, iObj))));
157 pObjHandler->AddObjects(vpObjects);
158 auto cmpResultObject = pObjHandler->CompareWithDefault();
159 for (int iVer = 0; iVer < nVersions; ++iVer) {
160 bCmpResult[iVer] = std::max(cmpResultObject[iVer], bCmpResult[iVer]);
161 }
162
163 if (!bSuppressCanvases
164 && (bForceCanvases || std::any_of(cmpResultObject.begin(), cmpResultObject.end(), [](auto i) {
165 return i != ECmpInference::StronglyEqual;
166 }))) {
167 pObjHandler->CreateCanvases(opt);
168 }
169 pObjHandler->Write();
170 gFile->Flush();
171
172 // Clean memory
173 for (auto* pObj : vpObjects) {
174 if (pObj) {
175 delete pObj;
176 pObj = nullptr;
177 }
178 }
179 } // iObj
180 LOG(info) << "FileHandler: processing objects: done";
181 return bCmpResult;
182}
183
184// ---------------------------------------------------------------------------------------------------------------------
185//
187{
188 if (fpOutputFile.get()) {
189 fpOutputFile->Flush();
190 fpOutputFile->Close();
191 fpOutputFile = nullptr;
192 fpOutDir = nullptr;
193 }
194 fpOutputFile = std::make_unique<TFile>(fpObjDB->GetOutputPath().c_str(), "UPDATE");
195 TString dirName = fpObjDB->GetDataset(fDatasetID) + "/" + fpObjDB->GetFileLabel(fFileID);
196 fpOutDir = fpOutputFile->Get<TDirectory>(dirName);
197}
A handler class to process versions from similar files (declaration)
Handler class for 1D-histograms (including TProfile objects) (declaration)
Handler class for 2D-histograms (implementation)
Handler class for 1D-profiles (implementation)
Handler for single files, created from different QA versions.
TDirectory * CreateNestedDirectory(const std::string &path)
Creates nested directory from a given path.
std::unique_ptr< TClonesArray > fpInputFiles
Pointer to input files array.
FileHandler(std::shared_ptr< ObjectDB > &pObjDB, int iDataset, int iFile)
Constructor.
std::unique_ptr< TFile > fpOutputFile
Pointer to output file.
std::vector< ECmpInference > Process(Option_t *opt="")
Processes comparison.
void ReOpenOutputFile()
Closes and opens output file.
TDirectory * fpOutDir
Pointer to output directory.
std::shared_ptr< ObjectDB > fpObjDB
Pointer to object database.
ECmpInference
The object comparison inference.
@ StronglyEqual
All the comparison methods gave equality.
@ Exact
exact equality (point-by-point, error-by-error)
@ Chi2
equality within a chi2 hypothesis test
@ Ratio
ratio equality (max and min ratios do not exceed a required range)