46 using ObjList_t = std::vector<std::pair<TObject*, TString>>;
57 CbmQaIO(TString prefixName, std::shared_ptr<ObjList_t> pObjList =
nullptr);
90 template<
typename T,
typename... Args>
91 T*
MakeQaObject(TString sName, TString sTitle, Args... args);
126 template<
class Config>
129 std::optional<Config> res = std::nullopt;
170 template<
typename T,
typename... Args>
200 if constexpr (std::is_base_of_v<CbmQaTable, T>) {
201 static_assert(
sizeof...(Args) == 3);
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);
210 T* pObj =
new T(sName.Data(), args...);
213 if constexpr (std::is_base_of_v<TH1, T>) {
214 pObj->SetDirectory(
nullptr);
218 if constexpr (std::is_same_v<TH1F, T> || std::is_same_v<TH1D, T> || std::is_same_v<TProfile, T>) {
221 else if constexpr (std::is_same_v<TH2F, T> || std::is_same_v<TH2D, T>) {
224 else if constexpr (std::is_same_v<TProfile2D, T>) {
227 else if constexpr (std::is_base_of_v<TCanvas, T>) {
228 auto* pListOfCanvases = gROOT->GetListOfCanvases();
229 if (-1 != pListOfCanvases->IndexOf(pObj)) {
230 pListOfCanvases->Remove(pObj);
236 if constexpr (std::is_base_of_v<CbmQaTable, T> || std::is_base_of_v<TCanvas, T>) {
238 sDirectory = TString(
"Summary/") + sDirectory;
244 if (sDirectory.Length() != 0) {
253 fpvObjList->push_back(std::make_pair(
static_cast<TObject*
>(pObj), sDirectory));
263 if constexpr (std::is_base_of_v<CbmQaTable, T>) {
264 static_assert(
sizeof...(Args) == 2);
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);
274 bool bUseConfig =
false;
277 if constexpr (std::is_base_of_v<TH1, T>) {
284 else if constexpr (std::is_base_of_v<TCanvas, T>) {
295 const char* title = sTitle.Data();
297 if constexpr (std::is_base_of_v<TH1, T>) {
298 const auto& tagNode =
fConfigNode[
"histograms"][sTagName.Data()];
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();
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>();
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>();
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>();
326 if constexpr (std::is_base_of_v<CbmQaTable, T>) {
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()));
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()));
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,
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()));
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()));