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