Project
Loading...
Searching...
No Matches
HistoManager.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <TDirectory.h>
13#include <TH1F.h>
14#include <TH2F.h>
15#include <TProfile.h>
16#include <TGraph.h>
17#include <TF1.h>
18#include <TFile.h>
19#include <TKey.h>
20#include <TList.h>
21#include <TNamed.h>
22#include <TPaveStats.h>
23#include <TROOT.h>
24#include <TSystem.h>
25#include "Framework/Logger.h"
27
28namespace o2
29{
30
31HistoManager::HistoManager(const std::string& dirname, const std::string& fname, bool load, const std::string& prefix) : mDirName(dirname)
32{
33 setFileName(fname);
34 if (load && !mDefName.empty()) {
35 int nh = this->load(fname, dirname);
36 LOGP(info, "HistoManager::load was requested: got {} histos from {}/{}", nh, fname, dirname);
37 if (!prefix.empty()) {
38 addPrefix(prefix);
39 }
40 }
41}
42
43HistoManager* HistoManager::createClone(const std::string& prefix) const
44{
45 auto* hm = static_cast<HistoManager*>(Clone());
46 hm->addPrefix(prefix);
47 for (int i = 0; i < GetLast() + 1; ++i) {
48 TObject* obj = hm->UncheckedAt(i);
49 if (!obj) {
50 continue;
51 }
52 if (auto* histo = dynamic_cast<TH1*>(obj)) {
53 histo->SetDirectory(nullptr);
54 }
55 }
56 hm->mNHistos = mNHistos;
57 hm->setFileName(mDefName);
58 hm->setDirName(mDirName);
59 return hm;
60}
61
62int HistoManager::addHisto(TH1* histo, int at)
63{
64 if (!histo) {
65 return mNHistos;
66 }
67 if (at < 0) {
68 at = mNHistos;
69 }
70 AddAtAndExpand(histo, at);
71 histo->SetDirectory(nullptr);
72 histo->SetUniqueID(at + 1);
73 return mNHistos++;
74}
75
76TGraph* HistoManager::getGraph(int id) const
77{
78 return id <= GetLast() ? dynamic_cast<TGraph*>(UncheckedAt(id)) : nullptr;
79}
80
81TH1* HistoManager::getHisto(int id) const
82{
83 return id <= GetLast() ? dynamic_cast<TH1*>(UncheckedAt(id)) : nullptr;
84}
85
86TH1* HistoManager::getHisto(const std::string& name) const
87{
88 return dynamic_cast<TH1*>(FindObject(name.c_str()));
89}
90
91TH1F* HistoManager::getHisto1F(int id) const
92{
93 return dynamic_cast<TH1F*>(UncheckedAt(id));
94}
95
96TH2F* HistoManager::getHisto2F(int id) const
97{
98 return dynamic_cast<TH2F*>(UncheckedAt(id));
99}
100
101TProfile* HistoManager::getHistoP(int id) const
102{
103 return dynamic_cast<TProfile*>(UncheckedAt(id));
104}
105
106int HistoManager::addGraph(TGraph* gr, int at)
107{
108 if (!gr) {
109 return mNHistos;
110 }
111 if (at < 0) {
112 at = mNHistos;
113 }
114 AddAtAndExpand(gr, at);
115 gr->SetUniqueID(at + 1);
116 return mNHistos++;
117}
118
120{
121 TObjArray::Compress();
122 for (int i = 0; i < GetLast() + 1; ++i) {
123 if (TObject* histo = At(i)) {
124 histo->SetUniqueID(i + 1);
125 }
126 }
127}
128
129void HistoManager::write(TFile* file)
130{
131 if (!mNHistos) {
132 return;
133 }
134
135 bool localFile = kFALSE;
136 TFile* lfile = nullptr;
137 const char* dirName = nullptr;
138 if (file) {
139 lfile = file;
140 } else {
141 auto* tmpF = static_cast<TFile*>(gROOT->GetListOfFiles()->FindObject(mDefName.c_str()));
142 if (tmpF && tmpF->IsOpen()) {
143 TString opt = tmpF->GetOption();
144 opt.ToLower();
145 if (!opt.Contains("read")) {
146 lfile = tmpF;
147 tmpF->cd();
148 }
149 }
150 }
151
152 TString pwd = gDirectory->GetPath();
153 if (!lfile) {
154 std::string originalName = mDefName;
155 if (mDefName.empty() || mDefName[0] == ' ') {
156 mDefName = "histoman";
157 }
158 TString rootName = mDefName.c_str();
159 if (!rootName.Contains(".root")) {
160 mDefName += ".root";
161 }
162 lfile = TFile::Open(mDefName.c_str(), "UPDATE");
163 mDefName = originalName;
164 localFile = kTRUE;
165 }
166
167 lfile->cd();
168 dirName = mDirName.c_str();
169 if (dirName && dirName[0] && dirName[0] != ' ') {
170 if (!lfile->Get(dirName)) {
171 lfile->mkdir(dirName);
172 }
173 lfile->cd(dirName);
174 }
175 LOGP(info, "Writing histograms to: {}/{}", lfile->GetPath(), dirName);
176
177 for (int i = 0; i < GetLast() + 1; ++i) {
178 TObject* obj = UncheckedAt(i);
179 if (!obj) {
180 continue;
181 }
182 auto* histo = dynamic_cast<TH1*>(obj);
183 TDirectory* dr = nullptr;
184 if (histo) {
185 dr = histo->GetDirectory();
186 histo->SetDirectory(nullptr);
187 }
188 obj->Write(nullptr, TObject::kOverwrite);
189 if (dr && histo) {
190 histo->SetDirectory(dr);
191 }
192 }
193
194 if (localFile) {
195 lfile->Close();
196 delete lfile;
197 }
198 auto* oldDir = static_cast<TDirectory*>(gROOT->GetListOfFiles()->FindObject(pwd.Data()));
199 if (oldDir) {
200 oldDir->cd();
201 }
202}
203
204void HistoManager::Clear(Option_t*)
205{
206 int nent = GetLast() + 1;
207 for (int i = 0; i < nent; ++i) {
208 TObject* hh = UncheckedAt(i);
209 if (!hh) {
210 continue;
211 }
212 RemoveAt(i);
213 --mNHistos;
214 }
215}
216
217//_______________________________________________________________
218void HistoManager::Delete(Option_t*)
219{
220 int nent = GetLast() + 1;
221 for (int i = 0; i < nent; ++i) {
222 TObject* hh = UncheckedAt(i);
223 if (!hh) {
224 continue;
225 }
226 RemoveAt(i);
227 delete hh;
228 }
229 mNHistos = 0;
230}
231
232void HistoManager::Print(Option_t* option) const
233{
234 int nent = GetLast() + 1;
235 for (int i = 0; i < nent; ++i) {
236 TObject* hh = UncheckedAt(i);
237 if (!hh) {
238 continue;
239 }
240 LOGP(info, "At position #{}", i);
241 hh->Print(option);
242 }
243 LOGP(info, "Total number of defined histograms: %d", mNHistos);
244 LOGP(info, "Current output path: {}/{}", mDefName, mDirName);
245}
246
247void HistoManager::addPrefix(const std::string& pref)
248{
249 if (pref.empty()) {
250 return;
251 }
252 int nent = GetLast() + 1;
253 for (int i = 0; i < nent; ++i) {
254 TObject* hh = UncheckedAt(i);
255 if (!hh) {
256 continue;
257 }
258 if (hh->InheritsFrom("TNamed")) {
259 auto name = pref + hh->GetName();
260 static_cast<TNamed*>(hh)->SetName(name.c_str());
261 }
262 }
263}
264
265void HistoManager::addHistos(const HistoManager* hm, Double_t c1)
266{
267 if (!hm) {
268 return;
269 }
270 int nent = GetLast() + 1;
271 int nent1 = hm->GetLast() + 1;
272 if (nent != nent1) {
273 Error("addHistos", "HistoManagers have different content: %d vs %d", nent, nent1);
274 return;
275 }
276 for (int i = 0; i < nent; ++i) {
277 TH1* hh1 = getHisto(i);
278 TH1* hh2 = hm->getHisto(i);
279 if (!hh1 || !hh2) {
280 continue;
281 }
282 hh1->Add(hh2, c1);
283 }
284}
285
287{
288 if (!hm) {
289 return;
290 }
291 int nent = GetLast() + 1;
292 int nent1 = hm->GetLast() + 1;
293 if (nent != nent1) {
294 Error("divideHistos", "HistoManagers have different content: %d vs %d", nent, nent1);
295 return;
296 }
297 for (int i = 0; i < nent; ++i) {
298 TH1* hh1 = getHisto(i);
299 TH1* hh2 = hm->getHisto(i);
300 if (!hh1 || !hh2) {
301 continue;
302 }
303 hh1->Divide(hh2);
304 }
305}
306
307//_______________________________________________________________
309{
310 if (!hm) {
311 return;
312 }
313 int nent = GetLast() + 1;
314 int nent1 = hm->GetLast() + 1;
315 if (nent != nent1) {
316 Error("multiplyHistos", "HistoManagers have different content: %d vs %d", nent, nent1);
317 return;
318 }
319 for (int i = 0; i < nent; ++i) {
320 TH1* hh1 = getHisto(i);
321 TH1* hh2 = hm->getHisto(i);
322 if (!hh1 || !hh2) {
323 continue;
324 }
325 hh1->Multiply(hh2);
326 }
327}
328
330{
331 int nent = GetLast() + 1;
332 for (int i = 0; i < nent; ++i) {
333 TH1* hh1 = getHisto(i);
334 if (hh1) {
335 hh1->Scale(c1);
336 }
337 }
338}
339
341{
342 int nent = GetLast() + 1;
343 for (int i = 0; i < nent; ++i) {
344 auto* hh1 = dynamic_cast<TH1*>(UncheckedAt(i));
345 if (hh1) {
346 hh1->Sumw2();
347 }
348 }
349}
350
351void HistoManager::setFile(TFile* file)
352{
353 if (file) {
354 mDefName = file->GetName();
355 }
356}
357
359{
360 TH1* hist = getHisto(at);
361 if (hist) {
362 RemoveAt(at);
363 delete hist;
364 --mNHistos;
365 }
366}
367
368void HistoManager::purify(bool emptyToo)
369{
370 int last = GetLast() + 1;
371 if (emptyToo) {
372 for (int i = 0; i < last; ++i) {
373 TH1* hist = getHisto(i);
374 if (!hist) {
375 continue;
376 }
377 if (hist->GetEntries() < 1) {
378 delHisto(i);
379 }
380 }
381 }
382 Compress();
383}
384
385void HistoManager::setFileName(const std::string& name)
386{
387 mDefName = gSystem->ExpandPathName(name.c_str());
388}
389
391{
392 int last = GetLast() + 1;
393 for (int i = 0; i < last; ++i) {
394 TH1* hist = getHisto(i);
395 if (!hist) {
396 continue;
397 }
398 hist->Reset();
399 }
400}
401
402int HistoManager::load(const std::string& fname, const std::string& dirname)
403{
404 TFile* file = TFile::Open(gSystem->ExpandPathName(fname.c_str()));
405 if (!file) {
406 LOGP(error, "No file {}", fname);
407 return 0;
408 }
409 if (!dirname.empty() && dirname[0] != ' ') {
410 if (!file->Get(dirname.c_str())) {
411 LOGP(error, "No {} directory in file {}", dirname, fname);
412 file->Close();
413 delete file;
414 return 0;
415 }
416 file->cd(dirname.c_str());
417 }
418 int count = 0;
419 TList* lst = gDirectory->GetListOfKeys();
420 TIter nextKey(lst);
421 TKey* key = nullptr;
422 while ((key = static_cast<TKey*>(nextKey()))) {
423 if (FindObject(key->GetName())) {
424 continue;
425 }
426 TString clName = key->GetClassName();
427 if (!(clName.BeginsWith("TH") || clName.BeginsWith("TProfile") || clName.BeginsWith("TGraph"))) {
428 printf("Object %s of type %s is not processed\n", key->GetName(), clName.Data());
429 continue;
430 }
431 TObject* hst = key->ReadObj();
432 int id = hst->GetUniqueID();
433 if (auto* h = dynamic_cast<TH1*>(hst)) {
434 addHisto(h, id - 1);
435 ++count;
436 continue;
437 }
438 if (auto* gr = dynamic_cast<TGraph*>(hst)) {
439 addGraph(gr, id - 1);
440 ++count;
441 }
442 }
443 file->Close();
444 delete file;
445 auto nm = fname;
446 if (!dirname.empty()) {
447 nm += fmt::format("/{}", dirname);
448 }
449 SetName(nm.c_str());
450 return count;
451}
452
454{
455 int last = GetLast() + 1;
456 for (int i = 0; i < last; ++i) {
457 TH1* hist = getHisto(i);
458 if (!hist) {
459 continue;
460 }
461 hist->SetLineColor(tcolor);
462 hist->SetMarkerColor(tcolor);
463 TList* lst = hist->GetListOfFunctions();
464 if (lst) {
465 int nf = lst->GetSize();
466 for (int j = 0; j < nf; ++j) {
467 TObject* fnc = lst->At(j);
468 if (fnc->InheritsFrom("TF1")) {
469 static_cast<TF1*>(fnc)->SetLineColor(tcolor);
470 static_cast<TF1*>(fnc)->SetLineWidth(1);
471 static_cast<TF1*>(fnc)->ResetBit(TF1::kNotDraw);
472 } else if (fnc->InheritsFrom("TPaveStats")) {
473 static_cast<TPaveStats*>(fnc)->SetTextColor(tcolor);
474 }
475 }
476 }
477 }
478}
479
480void HistoManager::setMarkerStyle(Style_t mstyle, Size_t msize)
481{
482 int last = GetLast() + 1;
483 for (int i = 0; i < last; ++i) {
484 TH1* hist = getHisto(i);
485 if (!hist) {
486 continue;
487 }
488 hist->SetMarkerStyle(mstyle);
489 hist->SetMarkerSize(msize);
490 }
491}
492
494{
495 int last = GetLast() + 1;
496 for (int i = 0; i < last; ++i) {
497 TH1* hist = getHisto(i);
498 if (!hist) {
499 continue;
500 }
501 hist->SetMarkerSize(msize);
502 }
503}
504
505} // namespace o2
int32_t i
uint32_t j
Definition RawData.h:0
StringRef key
Class for time synchronization of RawReader instances.
void purify(bool emptyToo=kFALSE)
void delHisto(int at)
TH1F * getHisto1F(int id) const
int addHisto(TH1 *histo, int at=-1)
void Compress() override
HistoManager * createClone(const std::string &prefix) const
void scaleHistos(Double_t c1=1.)
void addPrefix(const std::string &pref="")
void setMarkerStyle(Style_t mstyle=1, Size_t msize=1)
int load(const std::string &fname, const std::string &dirname="")
TProfile * getHistoP(int id) const
HistoManager(const std::string &dirname="", const std::string &fname="histoman.root", bool load=kFALSE, const std::string &prefix="")
void addHistos(const HistoManager *hm, Double_t c1=1.)
void Delete(Option_t *option="") override
void setColor(int tcolor=1)
void divideHistos(const HistoManager *hm)
void Clear(Option_t *option="") override
TGraph * getGraph(int id) const
void Print(Option_t *option="") const override
TH2F * getHisto2F(int id) const
void setMarkerSize(Size_t msize=1)
void write(TFile *file=nullptr)
TH1 * getHisto(int id) const
int addGraph(TGraph *gr, int at=-1)
void setFile(TFile *file)
void setFileName(const std::string &fname)
void multiplyHistos(const HistoManager *hm)
GLint GLsizei count
Definition glcorearb.h:399
GLuint const GLchar * name
Definition glcorearb.h:781
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...