CbmRoot
Loading...
Searching...
No Matches
CbmQaCmpDrawer.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 CbmQaCmpDrawer_h
11#define CbmQaCmpDrawer_h 1
12
13#include "Logger.h"
14#include "TH1.h"
15#include "TH2.h"
16#include "TH3.h"
17#include "TLegend.h"
18#include "TPad.h"
19
20#include <algorithm>
21#include <limits>
22#include <type_traits>
23#include <vector>
24
28template<class Obj>
30 public:
33
35 ~CbmQaCmpDrawer() = default;
36
39
42
45
48
50 void Clear();
51
55 void RegisterObject(const Obj* pObj, const char* title = nullptr);
56
60 void Draw(Option_t* opt) const;
61
66 void SetMinimum(double min) { fMinimum = min; }
67
73 void SetMaximum(double max) { fMaximum = max; }
74
75 private:
76 // Some constant expressions (TODO: move to a separate header)
77 static constexpr double kLegEntryHight = 0.06;
78 static constexpr double kLegEntryWidth = 0.35;
79 static constexpr double kLegRightBound = 0.99;
80 static constexpr double kLegTopBound = 0.90;
81 static constexpr double kLegTextSize = 0.04;
82 static constexpr double kIndentFromMax = 0.1;
83
84 double fMinimum = std::numeric_limits<double>::signaling_NaN();
85 double fMaximum = std::numeric_limits<double>::signaling_NaN();
86
87 std::vector<Obj*> fvpObjects;
88 std::vector<TString> fvsLegEntries;
89};
90
91
92// ****************************
93// ** Implementation **
94// ****************************
95
96// ---------------------------------------------------------------------------------------------------------------------
97//
98template<class Obj>
102
103// ---------------------------------------------------------------------------------------------------------------------
104//
105template<class Obj>
107{
108 fvpObjects.clear();
109 fvsLegEntries.clear();
110 fMinimum = std::numeric_limits<double>::signaling_NaN();
111 fMaximum = std::numeric_limits<double>::signaling_NaN();
112}
113
114// ---------------------------------------------------------------------------------------------------------------------
115//
116template<class Obj>
117void CbmQaCmpDrawer<Obj>::RegisterObject(const Obj* pObj, const char* title)
118{
119 if (!pObj) {
120 LOG(info) << "CbmQaCmpDrawer: attempt to register a nullptr (" << title << "), ignored";
121 return;
122 }
123
124 // Add entry to objects array
125 auto* pObjClone = static_cast<Obj*>(pObj->Clone());
126 fvpObjects.push_back(pObjClone);
127
128 // Add entry to legend
129 TString legEntryName = title ? title : pObj->GetTitle();
130 fvsLegEntries.push_back(legEntryName);
131}
132
133// ---------------------------------------------------------------------------------------------------------------------
134//
135template<class Obj>
136void CbmQaCmpDrawer<Obj>::Draw(Option_t* /*opt*/) const
137{
138 // TH1, TProfile
139 if constexpr (std::is_base_of_v<TH1, Obj> && !std::is_base_of_v<TH2, Obj> && !std::is_base_of_v<TH3, Obj>) {
140 // Maximum and minimum
141 double maxY = fMaximum;
142 if (std::isnan(maxY)) {
143 auto HistMax = [](const Obj* lhs, const Obj* rhs) { return lhs->GetMaximum() < rhs->GetMaximum(); };
144 maxY = (*std::max_element(fvpObjects.cbegin(), fvpObjects.cend(), HistMax))->GetMaximum();
145 maxY *= (1. + kIndentFromMax);
146 }
147 double minY = fMinimum;
148 if (std::isnan(minY)) {
149 auto HistMin = [](const Obj* lhs, const Obj* rhs) { return lhs->GetMinimum() < rhs->GetMinimum(); };
150 minY = (*std::min_element(fvpObjects.cbegin(), fvpObjects.cend(), HistMin))->GetMaximum();
151 minY = (minY < 0.) ? minY : 0.;
152 }
153
154 // Draw a stack of histograms
155 for (auto it = fvpObjects.begin(); it != fvpObjects.end(); ++it) {
156 (*it)->SetStats(false);
157 (*it)->SetMinimum(minY);
158 (*it)->SetMaximum(maxY);
159 (*it)->Draw(it == fvpObjects.begin() ? "" : "same");
160 }
161 }
162 else if constexpr (std::is_base_of_v<TH2, Obj> || std::is_base_of_v<TH3, Obj>) {
163 int nObjects = fvpObjects.size();
164 int nRows = static_cast<int>(std::sqrt(nObjects));
165 int nCols = nObjects / nRows;
166 if (nCols * nRows < nObjects) {
167 ++nCols;
168 }
169 gPad->Divide(nCols, nRows);
170
171 for (auto it = fvpObjects.begin(); it != fvpObjects.end(); ++it) {
172 if constexpr (std::is_base_of_v<TH2, Obj>) {
173 (*it)->Draw("colz");
174 }
175 else {
176 (*it)->Draw();
177 }
178 }
179 return; // do not draw legend
180 }
181
182 // Draw legend
183 double legX0 = kLegRightBound - kLegEntryWidth;
184 double legX1 = kLegRightBound;
185 double legY0 = kLegTopBound - kLegEntryHight * fvpObjects.size();
186 double legY1 = kLegTopBound;
187
188 auto* pLeg = new TLegend(legX0, legY0, legX1, legY1);
189 pLeg->SetTextSize(kLegTextSize);
190 for (int iObj = 0; iObj < (int) fvpObjects.size(); ++iObj) {
191 pLeg->AddEntry(fvpObjects[iObj], fvsLegEntries[iObj], "lp");
192 }
193 pLeg->Draw();
194}
195
196#endif // CbmQaCmpDrawer_h
friend fscal max(fscal x, fscal y)
friend fscal min(fscal x, fscal y)
Class to draw a comparison of objects on the provided canvas or pad.
std::vector< Obj * > fvpObjects
Set of objects to be drawn.
static constexpr double kLegEntryHight
Hight of one legend entry in Y axis.
std::vector< TString > fvsLegEntries
Entries to legend.
CbmQaCmpDrawer()
Default constructor.
~CbmQaCmpDrawer()=default
Destructor.
void SetMaximum(double max)
Sets maximum of the histogram/graph.
void Clear()
Clears the set of objects.
static constexpr double kLegTopBound
Top bound of the legend.
CbmQaCmpDrawer & operator=(const CbmQaCmpDrawer &)=delete
Copy assignment operator.
static constexpr double kIndentFromMax
Indent from the maximum (percentage from (max - min))
void Draw(Option_t *opt) const
Draw objects.
void SetMinimum(double min)
Sets minimum of the histogram/graph.
static constexpr double kLegRightBound
Right bound of the legend.
CbmQaCmpDrawer & operator=(CbmQaCmpDrawer &&)=delete
Move assignment operator.
CbmQaCmpDrawer(const CbmQaCmpDrawer &)=delete
Copy constructor.
void RegisterObject(const Obj *pObj, const char *title=nullptr)
Registers an object to draw.
static constexpr double kLegEntryWidth
Width of the legend.
static constexpr double kLegTextSize
Text size of the legend entries.
CbmQaCmpDrawer(CbmQaCmpDrawer &&)=delete
Move constructor.