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#include <yaml-cpp/yaml.h>
33
34
37
38// ---------------------------------------------------------------------------------------------------------------------
39//
40FileHandler::FileHandler(std::shared_ptr<ObjectDB>& pObjDB, int iDataset, int iFile)
41 : fFileID(iFile)
42 , fDatasetID(iDataset)
43 , fpObjDB(pObjDB)
44{
46 fpInputFiles = std::make_unique<TClonesArray>("TFile");
47
48 for (int iVer = 0; iVer < fpObjDB->GetNofVersions(); ++iVer) {
49 std::string filename = fpObjDB->GetInputFileName(iVer, fFileID, fDatasetID);
50 auto* pInFile = new ((*fpInputFiles)[iVer]) TFile(filename.data(), "READONLY");
51 LOG(info) << "File: " << pInFile->GetName();
52 LOG_IF(fatal, !pInFile->IsOpen()) << "FileHandler: file " << filename << " cannot be opened";
53 }
54
55 // Check registered folder
56 LOG_IF(fatal, !fpObjDB.get()) << "FileHandler: attempt to register a null pointer for the object database";
57 LOG_IF(fatal, !fpOutDir) << "FileHandler: attempt to register a null pointer for the output directory";
58 LOG_IF(fatal, fDatasetID < 0) << "FileHandler: attempt to register undefined dataset index";
59 LOG_IF(fatal, fFileID < 0) << "FileHandler: attempt to register undefined file index";
60}
61
62// ---------------------------------------------------------------------------------------------------------------------
63//
65{
66 // ----- Clean pointers
67 fpInputFiles->Delete();
68 fpInputFiles = nullptr;
69 fpOutputFile->Close();
70 fpOutputFile = nullptr;
71}
72
73// ---------------------------------------------------------------------------------------------------------------------
74//
75TDirectory* FileHandler::CreateNestedDirectory(const std::string& path)
76{
77 fpOutDir->mkdir(path.data());
78 return fpOutDir->GetDirectory(path.data());
79}
80
81// ---------------------------------------------------------------------------------------------------------------------
82//
83// Modified version of FileHandler::Process to use ObjectParameters
84std::vector<Result> FileHandler::Process()
85{
86 std::vector<Result> bCmpResult;
87 int nObjects = fpObjDB->GetNofObjects(fFileID);
88 int nVersions = fpObjDB->GetNofVersions();
89 bCmpResult.resize(nVersions, Result(ECmpInference::StronglyEqual, true, 1., 1., 1.));
90
91 if (!nObjects) {
92 LOG(warn) << "FileHandler: No objects were passed to file \"" << nObjects << ". Skipping file";
93 return bCmpResult;
94 }
95
96
97 LOG(info) << "Number of object parameters: " << fpObjDB->GetNofObjectParameters();
98 LOG(info) << "FileHandler: processing objects: ...";
99
100 // Initialize YAML node
101 YAML::Node yamlRoot;
102 yamlRoot["file_id"] = fFileID;
103 yamlRoot["dataset_id"] = fDatasetID;
104
105 for (int iObj = 0; iObj < nObjects; ++iObj) {
106 std::vector<TNamed*> vpObjects(nVersions, nullptr);
107 bool skipObj = false;
108 const auto& objPair = fpObjDB->GetObject(fFileID, iObj);
109 const std::string& objName = objPair.first;
110 const uint32_t paramIndex = objPair.second;
111 const auto& params = fpObjDB->GetObjectParameters(paramIndex);
112
113
114 for (int iVer = 0; iVer < nVersions; ++iVer) {
115 auto* pInputFile = static_cast<TFile*>(fpInputFiles->At(iVer));
116 if (!pInputFile) {
117 skipObj = true;
118 continue;
119 }
120 vpObjects[iVer] = dynamic_cast<TNamed*>(pInputFile->Get(objName.c_str()));
121 if (!vpObjects[iVer]) {
122 skipObj = true;
123 }
124 }
125
126 if (skipObj) continue;
127
128 std::string sOption = params.compMethod;
129 for (auto& ch : sOption)
130 ch = std::tolower(ch);
131 bool bSuppressCanvases = sOption.find("b") != std::string::npos;
132 bool bForceCanvases = sOption.find("c") != std::string::npos;
133 bool bCmpExact = sOption.find("e") != std::string::npos;
134 bool bCmpChi2 = sOption.find("s") != std::string::npos;
135 bool bCmpRatio = sOption.find("u") != std::string::npos;
136 bool bDumpResult = sOption.find("o") != std::string::npos;
137
138 if (iObj != 0 && iObj % 500 == 0) {
140 LOG(info) << "FileHandler: object " << iObj << " / " << nObjects;
141 }
142
143 std::unique_ptr<ObjectHandler> pObjHandler = nullptr;
144
145 if (dynamic_cast<TProfile*>(vpObjects[0])) {
146 pObjHandler = std::make_unique<Profile1DHandler>(iObj, fFileID, fDatasetID);
147 }
148 else if (dynamic_cast<TH2*>(vpObjects[0])) {
149 pObjHandler = std::make_unique<Hist2DHandler>(iObj, fFileID, fDatasetID);
150 }
151 else if (dynamic_cast<TH1*>(vpObjects[0])) {
152 pObjHandler = std::make_unique<Hist1DHandler>(iObj, fFileID, fDatasetID);
153 }
154 else {
155 LOG(warn) << "FileHandler: Object " << objName << " has a type \"" << vpObjects[0]->ClassName()
156 << "\", which is unknown to the checker framework, it will be skipped";
157 continue;
158 }
159 if (bCmpExact) {
160 pObjHandler->SetComparisonMethod(ECmpMethod::Exact); // Compare point-by-point (exact equality)
161 }
162 if (bCmpChi2) {
163 pObjHandler->SetComparisonMethod(ECmpMethod::Chi2); // Compare with chi2 test
164 }
165 if (bCmpRatio) {
166 pObjHandler->SetComparisonMethod(ECmpMethod::Ratio);
167 }
168 fpObjDB->SetRatioRange(params.ratioMin, params.ratioMax);
169 fpObjDB->SetPvalThreshold(params.pvalThreshold);
170 pObjHandler->SetObjectDB(fpObjDB);
171 pObjHandler->SetOutputDirectory(CreateNestedDirectory(objName));
172 pObjHandler->AddObjects(vpObjects);
173 auto cmpResultObject = pObjHandler->CompareWithDefault();
174
175
176 for (int iVer = 0; iVer < nVersions; ++iVer) {
177 bCmpResult[iVer].SetCmpInference(
178 std::max(cmpResultObject[iVer].GetCmpInference(), bCmpResult[iVer].GetCmpInference()));
179 }
180
181
182 if (!bSuppressCanvases
183 && (bForceCanvases || std::any_of(cmpResultObject.begin(), cmpResultObject.end(), [](auto i) {
184 return i.GetCmpInference() != ECmpInference::StronglyEqual;
185 }))) {
186 pObjHandler->CreateCanvases(sOption.c_str());
187 }
188 pObjHandler->Write();
189
190 // Write the comparison result to file
191 if (bDumpResult) {
192 for (int iVer = 0; iVer < nVersions; ++iVer) {
193 std::string name = "result_" + fpObjDB->GetVersionLabel(iVer);
194 cmpResultObject[iVer].Write(name.c_str());
195 //LOG(info) << "FileHandler: object " << iObj << " / " << nObjects
196 // << ", version " << iVer << ": " << cmpResultObject[iVer].GetPVal();
197 }
198 }
199
200 gFile->Flush();
201
202 for (auto*& pObj : vpObjects) {
203 delete pObj;
204 pObj = nullptr;
205 }
206 }
207
208
209 LOG(info) << "FileHandler: processing objects: done";
210 return bCmpResult;
211}
212
213// ---------------------------------------------------------------------------------------------------------------------
214//
216{
217 if (fpOutputFile.get()) {
218 fpOutputFile->Flush();
219 fpOutputFile->Close();
220 fpOutputFile = nullptr;
221 fpOutDir = nullptr;
222 }
223 fpOutputFile = std::make_unique<TFile>(fpObjDB->GetOutputPath().c_str(), "UPDATE");
224 TString dirName = fpObjDB->GetDataset(fDatasetID) + "/" + fpObjDB->GetFileLabel(fFileID);
225 fpOutDir = fpOutputFile->Get<TDirectory>(dirName);
226}
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)
FileHandler(std::shared_ptr< ObjectDB > &pObjDB, int iDataset, int iFile)
Constructor.
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.
std::vector< Result > Process()
Processes comparison.
std::unique_ptr< TFile > fpOutputFile
Pointer to output file.
void ReOpenOutputFile()
Closes and opens output file.
TDirectory * fpOutDir
Pointer to output directory.
std::shared_ptr< ObjectDB > fpObjDB
Pointer to object database.
A storable result of the QA-checker comparison routine.
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)