CbmRoot
Loading...
Searching...
No Matches
CbmQaIO.h
Go to the documentation of this file.
1/* Copyright (C) 2023-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko [committer] */
4
9
10#ifndef CbmQaIO_h
11#define CbmQaIO_h 1
12
13#include "CbmQaCanvas.h"
14#include "CbmQaEff.h"
15#include "CbmQaTable.h"
16#include "CbmYaml.h"
17#include "Logger.h"
18#include "TCanvas.h"
19#include "TEfficiency.h"
20#include "TH1.h"
21#include "TH2.h"
22#include "TH3.h"
23#include "TObject.h"
24#include "TParameter.h"
25#include "TProfile.h"
26#include "TProfile2D.h"
27#include "TProfile3D.h"
28#include "TROOT.h"
29#include "TString.h"
30
31#include <limits>
32#include <optional>
33#include <type_traits>
34#include <vector>
35
36#include <yaml-cpp/yaml.h>
37
38class TFile;
39
43class CbmQaIO {
44 public:
45 using ObjList_t = std::vector<std::pair<TObject*, TString>>;
46
47 enum class EStoringMode
48 {
51 };
52
56 CbmQaIO(TString prefixName, std::shared_ptr<ObjList_t> pObjList = nullptr);
57
59 virtual ~CbmQaIO();
60
62 CbmQaIO(const CbmQaIO&) = delete;
63
65 CbmQaIO(CbmQaIO&&) = delete;
66
68 CbmQaIO& operator=(const CbmQaIO&) = delete;
69
72
73
75 const char* GetConfigName() const { return fsConfigName.Data(); }
76
89 template<typename T, typename... Args>
90 T* MakeQaObject(TString sName, TString sTitle, Args... args);
91
99 void MakeQaDirectory(TString sName);
100
104 void SetConfigName(const char* path);
105
108 void SetRootFolderName(const TString& path) { fsRootFolderName = path.Strip(TString::kBoth, '/'); }
109
112
113 protected:
118 template<typename T>
119 void CheckProperty(T&& property, const char* name) const;
120
125 template<class Config>
126 std::optional<Config> ReadSpecificConfig() const
127 {
128 std::optional<Config> res = std::nullopt;
129 const auto& node = fConfigNode["specific"];
130 if (node) {
131 res = std::make_optional(cbm::util::yaml::Read<Config>(node));
132 }
133 return res;
134 }
135
138 virtual void SetTH1Properties(TH1* pHist) const;
139
142 virtual void SetTH2Properties(TH2* pHist) const;
143
146 virtual void SetTProfile2DProperties(TProfile2D* pHist) const;
147
150 virtual void SetCanvasProperties(TCanvas* pCanv) const;
151
154 void WriteToFile(TFile* pOutFile) const;
155
156 TString fsRootFolderName = "";
157 TString fsConfigName = "";
158 TString fsPrefix = "";
159
161 std::shared_ptr<ObjList_t> fpvObjList = nullptr;
162
163 YAML::Node fConfigNode{};
164
165 private:
169 template<typename T, typename... Args>
170 T* ConstructAndRegisterQaObject(TString name, Args... args);
171};
172
173
174// ---------------------------------------------------------------------------------------------------------------------
175//
176template<typename T>
177void CbmQaIO::CheckProperty(T&& property, const char* name) const
178{
179 bool bPropertyUndefined = false;
180 if constexpr (std::is_signed_v<T>) {
181 bPropertyUndefined = property < 0;
182 }
183 else if constexpr (std::is_floating_point_v<T>) {
184 bPropertyUndefined = std::isnan(property);
185 }
186
187 if (bPropertyUndefined) {
188 std::stringstream msg;
189 msg << "Property " << name << " is undefined in the configuration file";
190 throw std::runtime_error(msg.str());
191 }
192}
193
194// ---------------------------------------------------------------------------------------------------------------------
195//
196template<typename T, typename... Args>
197T* CbmQaIO::ConstructAndRegisterQaObject(TString sName, Args... args)
198{
199 if constexpr (std::is_base_of_v<CbmQaTable, T>) {
200 static_assert(sizeof...(Args) == 3);
201 }
202
203 // Resolve directory name and object name
204 auto iLastSlashPos = static_cast<int>(sName.Last('/'));
205 TString sDirectory = TString(sName(0, iLastSlashPos)).Strip(TString::kBoth, '/');
206 sName = sName(iLastSlashPos + 1, sName.Length() - iLastSlashPos);
207
208 // Create a new object
209 T* pObj = new T(sName.Data(), args...);
210
211 // Take object ownership from ROOT
212 if constexpr (std::is_base_of_v<TH1, T>) { // all kind of histograms
213 pObj->SetDirectory(nullptr);
214 }
215
216 // apply user-defined properties
217 if constexpr (std::is_same_v<TH1F, T> || std::is_same_v<TH1D, T> || std::is_same_v<TProfile, T>) { // histograms
218 SetTH1Properties(pObj);
219 }
220 else if constexpr (std::is_same_v<TH2F, T> || std::is_same_v<TH2D, T>) { // histograms
221 SetTH2Properties(pObj);
222 }
223 else if constexpr (std::is_same_v<TProfile2D, T>) { // profile 2D
225 }
226 else if constexpr (std::is_base_of_v<TCanvas, T>) { // canvases
227 auto* pListOfCanvases = gROOT->GetListOfCanvases();
228 if (-1 != pListOfCanvases->IndexOf(pObj)) {
229 pListOfCanvases->Remove(pObj);
230 }
232 }
233
234 // Define a "summary" subdirectory of canvases and tables
235 if constexpr (std::is_base_of_v<CbmQaTable, T> || std::is_base_of_v<TCanvas, T>) {
237 sDirectory = TString("Summary/") + sDirectory;
238 }
239 }
240
241 // Add parent directory
242 if (fsRootFolderName.Length() != 0) {
243 if (sDirectory.Length() != 0) {
244 sDirectory = fsRootFolderName + "/" + sDirectory;
245 }
246 else {
247 sDirectory = fsRootFolderName;
248 }
249 }
250
251 // Register the object in the list
252 fpvObjList->push_back(std::make_pair(static_cast<TObject*>(pObj), sDirectory));
253
254 return pObj;
255}
256
257// ---------------------------------------------------------------------------------------------------------------------
258//
259template<typename T, typename... Args>
260T* CbmQaIO::MakeQaObject(TString sName, TString sTitle, Args... args)
261{
262 if constexpr (std::is_base_of_v<CbmQaTable, T>) {
263 static_assert(sizeof...(Args) == 2);
264 }
265
266 // Resolve configuration tag, if any
267 auto iLastSepPos = static_cast<int>(sName.Last(';'));
268 TString sTagName = sName(iLastSepPos + 1, sName.Length() - iLastSepPos);
269 if (iLastSepPos != -1) {
270 sName = sName(0, iLastSepPos);
271 }
272
273 bool bUseConfig = false;
274 // Check, if parameters are provided for this tag
275 if (fConfigNode) {
276 if constexpr (std::is_base_of_v<TH1, T>) {
277 if (fConfigNode["histograms"]) {
278 if (fConfigNode["histograms"][sTagName.Data()]) {
279 bUseConfig = true;
280 }
281 }
282 }
283 else if constexpr (std::is_base_of_v<TCanvas, T>) {
284 if (fConfigNode["canvases"]) {
285 if (fConfigNode["canvases"][sTagName.Data()]) {
286 bUseConfig = true;
287 }
288 }
289 }
290 }
291
292 //LOG(info) << "CbmQaIO: init ROOT object \"" << sName << '\"'; // Debug
293
294 const char* title = sTitle.Data();
295 if (bUseConfig) {
296 if constexpr (std::is_base_of_v<TH1, T>) {
297 const auto& tagNode = fConfigNode["histograms"][sTagName.Data()];
298
299 [[maybe_unused]] int nBinsX = -1;
300 [[maybe_unused]] double minX = std::numeric_limits<double>::signaling_NaN();
301 [[maybe_unused]] double maxX = std::numeric_limits<double>::signaling_NaN();
302 [[maybe_unused]] int nBinsY = -1;
303 [[maybe_unused]] double minY = std::numeric_limits<double>::signaling_NaN();
304 [[maybe_unused]] double maxY = std::numeric_limits<double>::signaling_NaN();
305 [[maybe_unused]] int nBinsZ = -1;
306 [[maybe_unused]] double minZ = std::numeric_limits<double>::signaling_NaN();
307 [[maybe_unused]] double maxZ = std::numeric_limits<double>::signaling_NaN();
308
309 if (const auto& axisNode = tagNode["x"]) {
310 nBinsX = axisNode["nbins"].as<int>();
311 minX = axisNode["min"].as<double>();
312 maxX = axisNode["max"].as<double>();
313 }
314 if (const auto& axisNode = tagNode["y"]) {
315 nBinsY = axisNode["nbins"].as<int>();
316 minY = axisNode["min"].as<double>();
317 maxY = axisNode["max"].as<double>();
318 }
319 if (const auto& axisNode = tagNode["z"]) {
320 nBinsZ = axisNode["nbins"].as<int>();
321 minZ = axisNode["min"].as<double>();
322 maxZ = axisNode["max"].as<double>();
323 }
324
325 if constexpr (std::is_base_of_v<CbmQaTable, T>) {
326 return ConstructAndRegisterQaObject<T>(sName, title, args...);
327 }
328 else if constexpr (std::is_base_of_v<TProfile2D, T>) {
329 CheckProperty(nBinsX, Form("qa/histograms/%s/x/nbins", sTagName.Data()));
330 CheckProperty(minX, Form("qa/histograms/%s/x/min", sTagName.Data()));
331 CheckProperty(maxX, Form("qa/histograms/%s/x/max", sTagName.Data()));
332 CheckProperty(nBinsY, Form("qa/histograms/%s/y/nbins", sTagName.Data()));
333 CheckProperty(minY, Form("qa/histograms/%s/y/min", sTagName.Data()));
334 CheckProperty(maxY, Form("qa/histograms/%s/y/max", sTagName.Data()));
335 CheckProperty(minZ, Form("qa/histograms/%s/z/min", sTagName.Data()));
336 CheckProperty(maxZ, Form("qa/histograms/%s/z/max", sTagName.Data()));
337 return ConstructAndRegisterQaObject<T>(sName, title, nBinsX, minX, maxX, nBinsY, minY, maxY, minZ, maxZ);
338 }
339 else if constexpr (std::is_base_of_v<TProfile, T>) {
340 CheckProperty(nBinsX, Form("qa/histograms/%s/x/nbins", sTagName.Data()));
341 CheckProperty(minX, Form("qa/histograms/%s/x/min", sTagName.Data()));
342 CheckProperty(maxX, Form("qa/histograms/%s/x/max", sTagName.Data()));
343 CheckProperty(minY, Form("qa/histograms/%s/y/min", sTagName.Data()));
344 CheckProperty(maxY, Form("qa/histograms/%s/y/max", sTagName.Data()));
345 return ConstructAndRegisterQaObject<T>(sName, title, nBinsX, minX, maxX, minY, maxY);
346 }
347 else if constexpr (std::is_base_of_v<TH3, T>) {
348 CheckProperty(nBinsX, Form("qa/histograms/%s/x/nbins", sTagName.Data()));
349 CheckProperty(minX, Form("qa/histograms/%s/x/min", sTagName.Data()));
350 CheckProperty(maxX, Form("qa/histograms/%s/x/max", sTagName.Data()));
351 CheckProperty(nBinsY, Form("qa/histograms/%s/y/nbins", sTagName.Data()));
352 CheckProperty(minY, Form("qa/histograms/%s/y/min", sTagName.Data()));
353 CheckProperty(maxY, Form("qa/histograms/%s/y/max", sTagName.Data()));
354 CheckProperty(nBinsZ, Form("qa/histograms/%s/z/nbins", sTagName.Data()));
355 CheckProperty(minZ, Form("qa/histograms/%s/z/min", sTagName.Data()));
356 CheckProperty(maxZ, Form("qa/histograms/%s/z/max", sTagName.Data()));
357 return ConstructAndRegisterQaObject<T>(sName, title, nBinsX, minX, maxX, nBinsY, minY, maxY, nBinsZ, minZ,
358 maxZ);
359 }
360 else if constexpr (std::is_base_of_v<TH2, T>) {
361 CheckProperty(nBinsX, Form("qa/histograms/%s/x/nbins", sTagName.Data()));
362 CheckProperty(minX, Form("qa/histograms/%s/x/min", sTagName.Data()));
363 CheckProperty(maxX, Form("qa/histograms/%s/x/max", sTagName.Data()));
364 CheckProperty(nBinsY, Form("qa/histograms/%s/y/nbins", sTagName.Data()));
365 CheckProperty(minY, Form("qa/histograms/%s/y/min", sTagName.Data()));
366 CheckProperty(maxY, Form("qa/histograms/%s/y/max", sTagName.Data()));
367 return ConstructAndRegisterQaObject<T>(sName, title, nBinsX, minX, maxX, nBinsY, minY, maxY);
368 }
369 else if constexpr (std::is_base_of_v<TH1, T>) {
370 CheckProperty(nBinsX, Form("qa/histograms/%s/x/nbins", sTagName.Data()));
371 CheckProperty(minX, Form("qa/histograms/%s/x/min", sTagName.Data()));
372 CheckProperty(maxX, Form("qa/histograms/%s/x/max", sTagName.Data()));
373 return ConstructAndRegisterQaObject<T>(sName, title, nBinsX, minX, maxX);
374 }
375 }
376 }
377
378 return ConstructAndRegisterQaObject<T>(sName, title, args...);
379}
380
381#endif // CbmQaIO_h
Definition of the CbmQaCanvas class.
Declaration of CbmQaEff class.
Definition of CbmQaTable class.
CbmQaIO(const CbmQaIO &)=delete
Copy constructor.
CbmQaIO & operator=(const CbmQaIO &)=delete
Copy assignment operator.
T * MakeQaObject(TString sName, TString sTitle, Args... args)
Definition CbmQaIO.h:260
virtual void SetTProfile2DProperties(TProfile2D *pHist) const
Applies properties on the profile 2D created with the MakeQaObject function.
Definition CbmQaIO.cxx:67
virtual void SetCanvasProperties(TCanvas *pCanv) const
Applies properties on the canvas created with the MakeQaObject funciton.
Definition CbmQaIO.cxx:84
void SetConfigName(const char *path)
Creates a ROOT object.
Definition CbmQaIO.cxx:95
void WriteToFile(TFile *pOutFile) const
Writes objects into file.
Definition CbmQaIO.cxx:116
YAML::Node fConfigNode
Configuration node.
Definition CbmQaIO.h:163
void MakeQaDirectory(TString sName)
Definition CbmQaIO.cxx:132
virtual void SetTH2Properties(TH2 *pHist) const
Applies properties on the histogram created with the MakeQaObject function.
Definition CbmQaIO.cxx:50
std::optional< Config > ReadSpecificConfig() const
Reads the specific configuration structure from the YAML node.
Definition CbmQaIO.h:126
virtual ~CbmQaIO()
Destructor.
Definition CbmQaIO.cxx:31
TString fsPrefix
Unique prefix for all writeable root.
Definition CbmQaIO.h:158
void SetStoringMode(EStoringMode mode)
Set storing mode.
Definition CbmQaIO.h:111
const char * GetConfigName() const
Gets config name.
Definition CbmQaIO.h:75
virtual void SetTH1Properties(TH1 *pHist) const
Applies properties on the histogram created with the MakeQaObject function.
Definition CbmQaIO.cxx:36
std::shared_ptr< ObjList_t > fpvObjList
List of registered ROOT objects.
Definition CbmQaIO.h:161
CbmQaIO(TString prefixName, std::shared_ptr< ObjList_t > pObjList=nullptr)
Constructor.
Definition CbmQaIO.cxx:19
TString fsRootFolderName
Name of root folder.
Definition CbmQaIO.h:156
CbmQaIO & operator=(CbmQaIO &&)=delete
Move assignment operator.
EStoringMode
Definition CbmQaIO.h:48
@ kSUBDIR
Objects of different type will be stored in different subdirectories like histograms/ canvases/.
Definition CbmQaIO.h:50
@ kSAMEDIR
Objects of different type will be stored to root directory.
Definition CbmQaIO.h:49
void SetRootFolderName(const TString &path)
Sets a common root path to the objects in the output file.
Definition CbmQaIO.h:108
EStoringMode fStoringMode
Objects storing mode.
Definition CbmQaIO.h:160
CbmQaIO(CbmQaIO &&)=delete
Move constructor.
void CheckProperty(T &&property, const char *name) const
Function to check, if a property is defined.
Definition CbmQaIO.h:177
T * ConstructAndRegisterQaObject(TString name, Args... args)
Creates and registers a ROOT object.
Definition CbmQaIO.h:197
TString fsConfigName
Name of configuration file.
Definition CbmQaIO.h:157
std::vector< std::pair< TObject *, TString > > ObjList_t
Definition CbmQaIO.h:45
T Read(const YAML::Node &node)
Definition CbmYaml.h:74