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