43 {
44
45 class dbgPrint {
46
47 public:
48 dbgPrint(const debugLevel_t setLvl = none) : m_currLvl(setLvl) {};
49 inline void operator()(
const debugLevel_t level,
const std::string&
msg)
const {
50 if (level <= m_currLvl)
51 std::cout <<
msg << std::endl;
52 }
53 void setLvl(const debugLevel_t lvl) { m_currLvl = lvl; }
55
56 private:
58 };
59
60 static dbgPrint s_dbg;
61 static bool s_checkEquality=false;
62
63 std::optional<std::regex> checkRegEx(
const std::string&
re) {
65 return std::nullopt;
66
68 try {
69
70 std::string
test(
"Test String");
71 std::regex_match(test, reNew);
72 } catch (std::exception& e) {
73 std::cout <<
"ERROR: Invalid RegEx string \"" <<
re <<
"\"." << std::endl;
74 std::cout << "See https://en.cppreference.com/w/cpp/regex.html for allowed regular expression syntax" << std::endl;
75 return std::nullopt;
76 }
77 return reNew;
78 }
79
80
81
83 public:
84 explicit histCollection(TFile* out,
bool skipExisting =
false) : m_out{
out}, m_skipExisting(skipExisting) {};
86
88
89 void addDirectory(TDirectory* dir,
const std::string& dirName,
const std::string& filename =
"");
93
94 void addDirExclusion(const std::optional<std::regex>& dirEx);
95 void addHistExclusion(const std::optional<std::regex>& histEx);
96
97 unsigned size()
const;
99
102 return std::move(m_fileLBMap);
103 }
104
105 void printTiming();
106
107 private:
109 public:
110 histPerDir_t(
const std::string& nameIn, std::unique_ptr<TObject>&& objIn, TTree* md);
111 histPerDir_t(dqutils::histCollection::histPerDir_t&& other)
113
115 std::unique_ptr<TObject>
obj;
116 std::array<std::string, 3>
metadata{
"unset",
"",
"<default>"};
117 std::clock_t cpuSum = 0;
119 void merge(TObject* other);
120
121 private:
122 bool fillMD(TTree* mdTree);
123 };
124
126 std::unordered_map<std::string, histPerDir_t>
histos;
127 void writeMD(TDirectory* outDir) const;
128 };
129
130 private:
131 TFile* m_out;
132 bool m_skipExisting;
133 std::unordered_map<std::string, histDir_t>
m_data;
134 std::optional<std::regex> m_dirExclusion;
135 std::optional<std::regex> m_histExclusion;
137 };
138
139 void histCollection::clear() {
141 m_fileLBMap.clear();
142 }
143
144 void histCollection::printTiming() {
145 std::vector<std::pair<std::string, clock_t>> cpuPerHistVec;
147 for (auto& [histname, histo] : histDir.histos) {
148 cpuPerHistVec.emplace_back(
dirname +
"/" + histname,
histo.cpuSum);
149 }
150 }
151 auto ordering = [](std::pair<std::string, clock_t>
a, std::pair<std::string, clock_t>
b) {
return a.second <
b.second; };
152 std::sort(cpuPerHistVec.begin(), cpuPerHistVec.end(), ordering);
153 for (const auto& [name, time] : cpuPerHistVec) {
154 const double tSec =
double(time) / CLOCKS_PER_SEC;
155 std::cout << std::format("{:<30} : {:10.3f}", name, tSec) << std::endl;
156 }
157 return;
158 }
159
160 bool histCollection::histPerDir_t::fillMD(TTree * md) {
162 TTreeReaderArray<char> i_name(reader, "Name");
163 TTreeReaderArray<char> i_interval(reader, "Interval");
164 TTreeReaderArray<char> i_chain(reader, "TriggerChain");
165 TTreeReaderArray<char> i_merge(reader, "MergeMethod");
166
169 const std::string nameStr(static_cast<char*>(i_name.GetAddress()));
170 if (
name == nameStr) {
171 metadata = {
static_cast<char*
>(i_interval.GetAddress()),
static_cast<char*
>(i_chain.GetAddress()),
static_cast<char*
>(i_merge.GetAddress())};
173 break;
174 }
175 }
177 }
178
179 void histCollection::histPerDir_t::merge(TObject * other) {
180 if (obj && other) {
181 const std::clock_t cpuStart = std::clock();
182 this->mergeMethod(
obj.get(), other);
183 cpuSum += std::clock() - cpuStart;
184 }
185 return;
186 }
187
188 void histCollection::histDir_t::writeMD(TDirectory * out) const {
189
190
191 std::map<std::string, std::array<std::string, 3>> metadatamap;
192 std::unique_ptr<TTree> oldMD((TTree*)
out->Get(
"metadata"));
193 if (oldMD) {
194 TTreeReader
reader(oldMD.get());
195 TTreeReaderArray<char> i_name(reader, "Name");
196 TTreeReaderArray<char> i_interval(reader, "Interval");
197 TTreeReaderArray<char> i_chain(reader, "TriggerChain");
198 TTreeReaderArray<char> i_merge(reader, "MergeMethod");
199
201 const std::string
name(
static_cast<char*
>(i_name.GetAddress()));
202 metadatamap[
name] = {
static_cast<char*
>(i_interval.GetAddress()),
static_cast<char*
>(i_chain.GetAddress()),
static_cast<char*
>(i_merge.GetAddress())};
203 }
204 }
205
206 for (const auto& [key, h] : histos) {
207 if (
h.metadata[0]!=
"unset")
208 metadatamap[
key] =
h.metadata;
209 }
210
211 if (metadatamap.empty()) return;
214 std::unique_ptr<TTree> mdTree = std::make_unique<TTree>("metadata", "Monitoring Metadata");
215 mdTree->SetDirectory(out);
216
217 mdTree->Branch("Name", (void*)nullptr, "Name/C");
218 mdTree->Branch(
"Interval",
interval.data(),
"Interval/C");
219 mdTree->Branch(
"TriggerChain",
chain.data(),
"TriggerChain/C");
220 mdTree->Branch(
"MergeMethod",
merge.data(),
"MergeMethod/C");
221
222 mdTree->SetBranchAddress("Name", histname);
223
224 for (auto& [key, h] : metadatamap) {
225 strncpy(histname,
key.c_str(), 1023);
229 mdTree->Fill();
230 }
231 mdTree->Write(0, TObject::kOverwrite);
232 }
233
234 histCollection::~histCollection() {}
235
236 void histCollection::addDirExclusion(const std::optional<std::regex>& dir) {
237 m_dirExclusion =
dir;
238 return;
239 }
240
241 void histCollection::addHistExclusion(const std::optional<std::regex>& dir) {
242 m_histExclusion =
dir;
243 return;
244 }
245
248 for (
const auto& it :
m_data) {
249 s +=
it.second.histos.size();
250 }
252 }
253
255 for (
const auto& it :
m_data) {
257 std::cout <<
"Dir: " <<
it.first <<
" has " << hd.histos.size() <<
" histos" << std::endl;
258 for (const auto& it1 : hd.histos)
259 std::cout << "\t" << it1.second.name << std::endl;
260 }
261 return;
262 }
263
264 template <class HIST>
266 static_cast<HIST*
>(
a)->Add(
static_cast<const HIST*
>(b));
267 return;
268 }
269
271 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
272 const TH1* b1 =
dynamic_cast<const TH1*
>(
b);
273 if (!b1 || !a1)
274 std::cout << "ERROR in weightedAverageTH1: Object not of type TH1" << std::endl;
275 else {
276 if (b1->GetEntries()==0) return;
278 }
279 return;
280 }
281
283 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
284 const TH1* b1 = (
dynamic_cast<const TH1*
>(
b));
285 if (!b1 || !a1)
286 std::cout << "ERROR in weightedEff: Object not of type TH1" << std::endl;
287 else {
288 if (b1->GetEntries()==0) return;
290 }
291 return;
292 }
293
295 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
296 const TH1* b1 =
dynamic_cast<const TH1*
>(
b);
297 if (!b1 || !a1)
298 std::cout << "ERROR in mergeRMS: Object not of type TH1" << std::endl;
299 else {
300 if (b1->GetEntries()==0) return;
302 }
303 return;
304 }
305
307 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
308 const TH1* b1 =
dynamic_cast<const TH1*
>(
b);
309 if (!b1 || !a1)
310 std::cout << "ERROR in RMSpercentDeviation: Object not of type TH1" << std::endl;
311 else {
312 if (b1->GetEntries()==0) return;
314 }
315 return;
316 }
317
319 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
320 const TH1* b1 =
dynamic_cast<const TH1*
>(
b);
321 if (!b1 || !a1)
322 std::cout << "ERROR in getBinEffPerCent: Object not of type TH1" << std::endl;
323 else {
324 if (b1->GetEntries()==0) return;
326 }
327 return;
328 }
329
331 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
332 const TH1* b1 =
dynamic_cast<const TH1*
>(
b);
333 if (!b1 || !a1)
334 std::cout << "ERROR in lowerLB: Object not of type TH1" << std::endl;
335 else
337 return;
338 }
339
340 template <class HIST>
341 void identical(TObject *
a,
const TObject* b) {
342 if (!s_checkEquality)
343 return;
344 HIST* a1 = (
dynamic_cast<HIST*
>(
a));
345 const HIST* b1 =
dynamic_cast<const HIST*
>(
b);
346 if (!b1 || !a1){
347 std::cout << "ERROR in identical: Object not of correct type" << std::endl;
348 return;
349 }
351 return;
352 }
353
354 void merge_rebinned(TObject *
a,
const TObject* b) {
355 TH1* a1 = (
dynamic_cast<TH1*
>(
a));
356 const TH1* b1 =
dynamic_cast<const TH1*
>(
b);
357 if (!a1 || !b1) {
358 std::cout << "ERROR, in merge_rebinned: Object not of type TH1";
359 return;
360 }
361 TH1* b2 = const_cast<TH1*>(b1);
363 return;
364 }
365
366 void merge_eventSample(TObject *
a,
const TObject* b) {
367 TH2* a1 = (
dynamic_cast<TH2*
>(
a));
368 const TH2* b1 =
dynamic_cast<const TH2*
>(
b);
369 if (!a1 || !b1) {
370 std::cout << "ERROR in merge_eventSample: Object not of type TH2" << std::endl;
371 return;
372 }
374 }
375
376 void merge_TEfficency(TObject *
a,
const TObject* b) {
377 TEfficiency* a1 =
dynamic_cast<TEfficiency*
>(
a);
378 const TEfficiency* b1 =
dynamic_cast<const TEfficiency*
>(
b);
379 TEfficiency* b2 = const_cast<TEfficiency*>(b1);
380 if (!a1 || !b1) {
381 std::cout << "ERROR in merge_TEfficiency: Object not of type TEfficiency" << std::endl;
382 return;
383 }
384 TList listE;
385 listE.Add(b2);
386 a1->Merge(&listE);
387 listE.Clear();
388 }
389
390 void merge_TTree(TObject *
a,
const TObject* b) {
391 TTree* a1 =
dynamic_cast<TTree*
>(
a);
392 const TTree* b1 =
dynamic_cast<const TTree*
>(
b);
393 if (!a1 || !b1) {
394 std::cout << "ERROR in merge_TTree: Object not of type TTree" << std::endl;
395 return;
396 }
397 TTree* b2 = const_cast<TTree*>(b1);
398 TList listT;
399 listT.Add(b2);
400 a1->Merge(&listT);
401 listT.Clear();
402 }
403
405 :
name(nameIn),
obj(std::move(objIn)), mergeMethod(nullptr) {
406
407 if (!obj) {
408 std::cout << "ERROR while adding " << nameIn << ": Histogram pointer is NULL" << std::endl;
409 return;
410 }
411
412 if (mdTree) {
413 fillMD(mdTree);
414 }
415 else {
416 s_dbg(VERBOSE,"No matadata found for " + name +", use defaults");
417 }
418 const std::string& howToMerge =
metadata[2];
419 s_dbg(VERBOSE, "Name: " + name + " mergeMethod=" + howToMerge);
420
421 TH1* th1 =
dynamic_cast<TH1*
>(
obj.get());
422 TH2* th2 =
dynamic_cast<TH2*
>(
obj.get());
423 TEfficiency* teff =
dynamic_cast<TEfficiency*
>(
obj.get());
424 if (th1) {
425 th1->SetDirectory(nullptr);
426 if (howToMerge == "<default>") {
427 if (th2) {
429 } else {
431 }
432 }
433 else if (howToMerge == "weightedAverage" || howToMerge=="weightedAverage2D")
434 mergeMethod = &weightedAverage;
435 else if (howToMerge == "weightedEff")
436 mergeMethod = &weightedEff;
437 else if (howToMerge == "mergeRMS")
438 mergeMethod = &mergeRMS;
439 else if (howToMerge == "RMSpercentDeviation")
440 mergeMethod = &RMSpercentDeviation;
441 else if (howToMerge == "perBinEffPerCent")
442 mergeMethod = &perBinEffPerCent;
443 else if (howToMerge == "lowerLB")
445 else if (howToMerge == "identical")
446 if (th2) {
447 mergeMethod = &identical<TH2>;
448 } else {
449 mergeMethod = &identical<TH1>;
450 }
451 else if ((howToMerge == "mergeRebinned") || (howToMerge == "merge"))
452 mergeMethod = &merge_rebinned;
453 else {
454 std::cout << "ERROR: Unknown merging method (" << howToMerge << ") for object of type TH1 named " << nameIn << std::endl;
456 }
457 }
458 else if (teff) {
459 teff->SetDirectory(nullptr);
460 if (howToMerge == "<default>")
461 mergeMethod = &merge_TEfficency;
462 else
463 std::cout << "ERROR: Unknown merging method (" << howToMerge << ") for object of type TEfficiency named " << nameIn << std::endl;
464 }
465 else if (
nullptr !=
dynamic_cast<TTree*
>(
obj.get())) {
466 mergeMethod = &merge_TTree;
467 } else {
468 std::cout <<
"ERROR Object " <<
name <<
" has unkown type" << std::endl;
470 }
471 }
472
474
475 s_dbg(VERBOSE, "Working on directory " + dirName);
476 if (m_dirExclusion && !std::regex_search(dirName, *m_dirExclusion)) {
477 s_dbg(
DEBUG,
"Path " + dirName +
" is excluded");
478 return;
479 }
480
481 for (TObject* oKey : *
dir->GetListOfKeys()) {
482 TKey*
key =
static_cast<TKey*
>(oKey);
483 const std::string
name =
key->GetName();
484 const std::string classname =
key->GetClassName();
485 if ((classname == "TTree") && (name == "metadata")) {
486 continue;
487 }
488
489 s_dbg(VERBOSE, "Found name " + name + ", classname=" + classname);
490
492 auto itDir =
m_data.find(dirName);
493
494 if (classname.starts_with("TH") || classname.starts_with("TProfile") || classname.starts_with("TEfficiency") || classname == "TTree") {
495 if (m_histExclusion && !std::regex_search(name, *m_histExclusion)) {
496 s_dbg(
DEBUG,
"Histogram with name " + name +
" is excluded");
497 continue;
498 }
499
500
501 if (m_skipExisting) {
502
503 std::unique_ptr<TObject> existingObj(m_out->Get(
newName.c_str()));
504 if (existingObj)
505 continue;
506 }
507
508 std::unique_ptr<TTree> md;
509 if (itDir ==
m_data.end()) {
510
512 s_dbg(VERBOSE, "Registering new directory " + dirName);
513 }
514
515
516 auto itH = itDir->second.histos.find(name);
517 if (itH == itDir->second.histos.end()) {
518
519 if (!md) {
520
521 md.reset((TTree*)
dir->Get(
"metadata"));
522 }
523
524 std::unique_ptr<TObject>
obj{
key->ReadObj()};
525 TTree* treeObj =
dynamic_cast<TTree*
>(
obj.get());
526 if (treeObj) {
527 TDirectory* outDir = m_out->GetDirectory(
dirName.c_str());
528 if (!outDir)
529 outDir = m_out->mkdir(
dirName.c_str());
530
532 outDir->cd();
533 TTree* cloneTree = treeObj->CloneTree();
534
535 obj.reset(cloneTree);
537 }
539 itH = itDir->second.histos.emplace(name, std::move(histo)).first;
540 s_dbg(VERBOSE, "Cloning histogram " + name + " in dir " + dirName);
541 } else {
542
543 std::unique_ptr<TObject>
other(
key->ReadObj());
544 if (!other) {
545 std::cout << "ERROR, got NULL key";
546 } else {
547 itH->second.merge(
other.get());
548 s_dbg(VERBOSE, "Merging histogram " + name + " in dir " + dirName);
549 }
550 }
551 } else if (classname.starts_with("TDirectory")) {
552 std::unique_ptr<TObject>
obj(
key->ReadObj());
553 TDirectory*
subdir =
dynamic_cast<TDirectory*
>(
obj.get());
554 if (subdir) {
557 } else {
558 if (!
name.starts_with(
"lb_") && !
name.starts_with(
"lowStat_LB")) {
560 } else {
561 m_fileLBMap[
newName].insert(filename);
562 }
563 }
564 }
565 } else {
566 std::cout <<
"Ignored objects '" <<
name <<
"' of type " << classname << std::endl;
567 }
568 }
569 return;
570 }
571
574 unsigned nIgnored = 0;
575 unsigned nDirs = 0;
578 TDirectory* histDir = m_out->GetDirectory(
fulldir.c_str());
579 if (histDir == nullptr) {
580 histDir = m_out->mkdir(
fulldir.c_str());
581 if (histDir == nullptr) {
582 std::cout <<
"ERROR, failed to create directory " <<
fulldir << std::endl;
583 break;
584 } else {
585 s_dbg(VERBOSE, "Created directory " + fulldir + " in file " + m_out->GetName());
586 }
587 }
589 ++nDirs;
590 for (
auto& [name, histo] :
it.second.histos) {
594 } else {
595 std::cout <<
"NOT writing " <<
name <<
". Invalid." << std::endl;
596 ++nIgnored;
597 }
598 }
599 it.second.writeMD(histDir);
600 }
601 std::cout <<
"Wrote " <<
nWritten <<
" histograms to " << nDirs <<
" directories in output file " << m_out->GetName() << std::endl;
602 if (nIgnored)
603 std::cout << " Omitting " << nIgnored << " histograms." << std::endl;
604 }
605
606
607
608
609
610 MonitoringFile::OutputMetadata::OutputMetadata(TTree * metadata) : m_metadata(
metadata) {
611 makeBranch("Name", "Name/C");
612 makeBranch("Interval", "Interval/C");
613 makeBranch("TriggerChain", "TriggerChain/C");
614 makeBranch("MergeMethod", "MergeMethod/C");
615 }
616
617 void MonitoringFile::OutputMetadata::makeBranch(const char* branchName, const char* branchstr) {
618 if (!m_metadata->GetBranch(branchName)) {
619 m_metadata->Branch(branchName, (void*)nullptr, branchstr);
620 }
621 }
622
623 void MonitoringFile::OutputMetadata::fill(const std::string& theName, const std::string& theInterval, const std::string& theChain,
624 const std::string& theMerge) {
625 std::string
name = theName;
627 std::string
chain = theChain;
628 std::string
merge = theMerge;
629 m_metadata->SetBranchAddress(
"Name",
name.data());
630 m_metadata->SetBranchAddress(
"Interval",
interval.data());
631 m_metadata->SetBranchAddress(
"TriggerChain",
chain.data());
632 m_metadata->SetBranchAddress(
"MergeMethod",
merge.data());
633 m_metadata->Fill();
634 }
635
636 MonitoringFile::MonitoringFile() : m_file(0) {
637 m_fileCompressionLevel = 1;
638 m_doTiming = false;
639 MonitoringFile::clearData();
640 }
641
642 bool MonitoringFile::setFile(const std::string& fileName) {
643 clearData();
644 m_file = TFile::Open(
fileName.c_str());
645 if (m_file != 0)
646 return true;
647 return false;
648 }
649
650 MonitoringFile::MonitoringFile(const std::string& fileName) : m_file(0) {
651 m_fileCompressionLevel = 1;
652 m_doTiming = false;
653 MonitoringFile::clearData();
654 MonitoringFile::setFile(fileName);
655 }
656
657 MonitoringFile::~MonitoringFile() {
659
660 delete m_file;
661 }
662
663 bool MonitoringFile::setHistogramRegEx(
const std::string&
re) {
664 m_mergeMatchHistoRE = checkRegEx(
re);
665 return m_mergeMatchHistoRE.has_value();
666 }
667
668 bool MonitoringFile::setDirectoryRegEx(
const std::string&
re) {
669 m_mergeMatchDirRE = checkRegEx(
re);
670 return m_mergeMatchDirRE.has_value();
671 }
672
673 void MonitoringFile::getAllDirs(DirMap_t & dirmap, TDirectory * dir, const std::string& dirName) {
674 if (dir == 0)
675 return;
676
677 if (dirName != "") {
678 DirMap_t::value_type dirmapVal(dirName, dir);
679 dirmap.insert(std::move(dirmapVal));
680 }
681
682 TIter
next(
dir->GetListOfKeys());
684 while ((key =
dynamic_cast<TKey*
>(
next())) != 0) {
685
686 TObject*
obj =
key->ReadObj();
687 TDirectory*
subdir =
dynamic_cast<TDirectory*
>(
obj);
688 if (subdir != 0) {
689 std::string subdirName(
subdir->GetName());
690 std::string
fName(
"");
691 if (dirName != "") {
694 }
696 getAllDirs(dirmap, subdir, fName);
697 } else {
699 }
700 }
701 }
702
703 TDirectory* MonitoringFile::createDir(DirMap_t & dirmap, TDirectory * dir, const std::string& parent, const std::string& path) {
704 if (dir == 0)
705 return 0;
706
708 DirMap_t::const_iterator diter;
709 std::string::size_type
i =
path.find_first_of(
'/');
710 std::string
fName(
"");
711 if (parent != "") {
714 }
715
716 if (i != std::string::npos) {
717 std::string dName(path, 0, i);
718 std::string pName(path, i + 1, std::string::npos);
720 if (dName != "") {
721 diter = dirmap.find(fName);
722 if (diter != dirmap.end()) {
724 } else {
726 DirMap_t::value_type dirmapVal(fName, subdir);
727 dirmap.insert(std::move(dirmapVal));
728 }
729 } else {
731 }
732 return createDir(dirmap, subdir, fName, pName);
733 }
734
736
737 diter = dirmap.find(fName);
738 if (diter != dirmap.end()) {
739 return diter->second;
740 }
741
743 DirMap_t::value_type dirmapVal(fName, subdir);
744 dirmap.insert(std::move(dirmapVal));
746 }
747
748 TKey* MonitoringFile::getObjKey(TDirectory * dir, const std::string& path) {
749 if (dir == 0)
750 return 0;
751
753
754 std::string::size_type
i =
path.find_first_of(
'/');
755 if (i != std::string::npos) {
756 std::string dName(path, 0, i);
757 std::string pName(path, i + 1, std::string::npos);
758 if (dName != "") {
759 key =
dir->FindKey(dName.c_str());
760 if (key != 0) {
761 TDirectory* subDir =
dynamic_cast<TDirectory*
>(
key->ReadObj());
762 if (subDir) {
764 }
765 }
766 return 0;
767 }
769 }
770
771 return dir->FindKey(
path.c_str());
772 }
773
774 void MonitoringFile::fillMetaDataMap(std::map<std::string, dqutils::MonitoringFile::MetaData> & mdMap, TDirectory * dir) {
775 if (dir == 0)
776 return;
777 TTree* md =
dynamic_cast<TTree*
>(
dir->Get(
"metadata"));
778 if (md == 0)
779 return;
780
782 TTreeReaderArray<char> i_name(reader, "Name");
783 TTreeReaderArray<char> i_interval(reader, "Interval");
784 TTreeReaderArray<char> i_chain(reader, "TriggerChain");
785 TTreeReaderArray<char> i_merge(reader, "MergeMethod");
786
788 const std::string nameStr(static_cast<char*>(i_name.GetAddress()));
789 if (mdMap.find(nameStr) == mdMap.end()) {
790 MetaData md(nameStr, static_cast<char*>(i_interval.GetAddress()), static_cast<char*>(i_chain.GetAddress()), static_cast<char*>(i_merge.GetAddress()));
791 std::map<std::string, MetaData>::value_type mdVal(nameStr, md);
792 mdMap.insert(std::move(mdVal));
793 }
794 }
795
796 delete md;
797 }
798
799 int MonitoringFile::mergeFiles(
const std::string & outFileName,
const std::vector<std::string>&
files, fileLBMap_t& lbmap,
bool fillLBDirs) {
800 std::cout <<
"Writing file: " <<
outFileName << std::endl;
801 std::cout <<
"Start merging [" <<
files.size() <<
"] histogram files" << std::endl;
803 TH1::AddDirectory(false);
804 if (m_mergeMatchDirRE.has_value() || m_mergeMatchHistoRE.has_value()) {
805 std::cout << " ========== Using regular expressions for selective merging ========== " << std::endl;
806 }
807 if (m_doTiming) {
808 std::cout << "CPU time measurement activated " << std::endl;
809 }
810
812
813 if (nFiles < 1)
814 return -1;
815
816 if (nFiles == 1) {
817 std::cout << "Got exactly one input file. Will copy input -> output" << std::endl;
818 if (m_mergeMatchDirRE.has_value() || m_mergeMatchHistoRE.has_value()) {
819 std::cout << "regular expressions for selective merging will have no effect!" << std::endl;
820 }
821
823 std::filesystem::path
outPath(outFileName);
824 std::filesystem::copy_file(inPath, outPath, std::filesystem::copy_options::overwrite_existing);
825 return 0;
826 }
827
830 std::cout <<
" ERROR, cound not open output file " <<
outFileName << std::endl;
831 return -1;
832 }
833 std::cout <<
"Opened/created output file " <<
outFileName << std::endl;
834
836 hc.addDirExclusion(m_mergeMatchDirRE);
837 hc.addHistExclusion(m_mergeMatchHistoRE);
838
839
840 std::unique_ptr<TFile> in1(TFile::Open(
files[0].c_str()));
841 if (!in1) {
842 std::cout <<
"ERROR, could not open input file " <<
files[0] << std::endl;
843 return -1;
844 }
845 std::cout <<
"Working on file 1/" <<
nFiles <<
": " <<
files[0] << std::endl;
846 std::string runDir, runDirFwd;
847 const std::regex runDirPattern("run_[0-9]*");
848 TIter
next(in1->GetListOfKeys());
850 while ((key = (TKey*)
next())) {
851 const char*
name =
key->GetName();
852 if (std::regex_match(name, runDirPattern)) {
853 if (runDir.size() > 0) {
854 std::cout <<
"ERROR More than one run_XXX directory found! Ignoring " <<
name << std::endl;
855 } else
857 }
858 }
859 if (runDir.empty()) {
860 std::cout << "No run-directory found, start with '/'" << std::endl;
861 runDir="/";
862 runDirFwd="";
863 }
864 else {
865 std::cout << "Found run directory " << runDir << std::endl;
866 runDirFwd=runDir;
867 }
868
869
870 TDirectory*
dir(
dynamic_cast<TDirectory*
>(in1->GetDirectory(runDir.c_str())));
871 if (!dir) {
872 std::cout << "ERROR, can't access directory " << runDir;
873 return -1;
874 }
875
876 hc.addDirectory(dir, runDirFwd,
files[0]);
877
878
879 in1.reset(nullptr);
880
881 for (
size_t i = 1;
i <
files.size(); ++
i) {
882 std::cout <<
"Working on file " << 1+
i <<
"/" <<
nFiles <<
": " <<
files[
i] << std::endl;
883 std::unique_ptr<TFile> in(TFile::Open(
files[i].c_str()));
884 if (!in) {
885 std::cout <<
"ERROR, could not open input file " <<
files[
i] << std::endl;
886 return -1;
887 }
888 TDirectory*
dir(
dynamic_cast<TDirectory*
>(in->GetDirectory(runDir.c_str())));
889 if (not dir){
890 std::cout << "ERROR, could not cast to directory" << std::endl;
891 return -1;
892 }
893 hc.addDirectory(dir, runDirFwd,
files[i]);
894 }
895
896 std::cout << "Accumulated a total of " << hc.size() << " histograms." << std::endl;
897
898 std::cout << "Start writing output ..." << std::endl;
899 hc.write();
900
901 if (m_doTiming) {
902 std::cout << "CPU time for histogram merging: (regular histograms)" << std::endl;
903 hc.printTiming();
904 }
905
906 auto newlbmap = hc.getFileLBMapAndClear();
907
908
909 for (auto& [lbname, newfileset] : newlbmap) {
910 auto& fileset = lbmap[lbname];
911 fileset.merge(newfileset);
912 }
913
914 if (!lbmap.empty() && fillLBDirs) {
915 std::cout << "Start merging lb_nnn and lowStat_LB directories (" << lbmap.size() << " in total)" << std::endl;
916
918 hclb.addDirExclusion(m_mergeMatchDirRE);
919 hclb.addHistExclusion(m_mergeMatchHistoRE);
920
921
922
923 std::vector<std::pair<std::string, std::vector<std::string>>> lbToFiles;
924 for (
const auto& [
lb,fileSet] : lbmap) {
925 if (fileSet.size() > 0)
926 lbToFiles.emplace_back(
lb,std::vector<std::string>(fileSet.begin(),fileSet.end()));
927 }
928
929
930 std::sort(lbToFiles.begin(), lbToFiles.end(),
931 [](
const decltype(lbToFiles)
::value_type&
a,
const decltype(lbToFiles)
::value_type& b) { return a.second[0] < b.second[0]; });
932
934 std::unique_ptr<TFile> in;
935 for (const auto& [dir, filenames] : lbToFiles) {
936 std::cout <<
"Merging/copying directory " <<
dir <<
" from " <<
filenames.size() <<
" input file(s) (" << ++
counter <<
"/" << lbToFiles.size() <<
")"
937 << std::endl;
938 for (const std::string& fName : filenames) {
939 if (!in || strcmp(in->GetName(),
fName.c_str()) != 0) {
940 in.reset(TFile::Open(
fName.c_str()));
941 s_dbg(
DEBUG,
"Opening input file " + fName);
942 } else {
943 s_dbg(
DEBUG,
"Input file " + fName +
" already open");
944 }
945
946 if (!in) {
947 std::cout <<
"ERROR, could not open input file " <<
fName << std::endl;
948 return -1;
949 }
950 TDirectory* tDir = (
dynamic_cast<TDirectory*
>(in->Get(
dir.c_str())));
951 if (!tDir) {
952 std::cout <<
"ERROR, failed to get directory " <<
dir <<
" from file " <<
fName << std::endl;
953 } else {
954 hclb.addDirectory(tDir, dir);
955 }
956 }
957 hclb.write();
958 if (m_doTiming) {
959 std::cout << "CPU time for histogram merging: (lumiblock-histograms)" << std::endl;
960 hclb.printTiming();
961 }
962 hclb.clear();
963 }
964 in.reset(nullptr);
965 }
966 return 0;
967 }
968
969 int MonitoringFile::mergeFiles(const std::string& outFileName, const std::string& listFileName) {
970 typedef std::vector<std::string> FileList_t;
971
972 const unsigned int nFilesAtOnce = 50;
973
975 bool success = setListFromFile(allFiles, listFileName);
976 if (!success) {
977 std::cout << "ERROR Failed ot read list of input files" << std::endl;
978 return -1;
979 }
980
981
983 if (
allFiles.size() <= nFilesAtOnce) {
984 return mergeFiles(outFileName, allFiles, fileLBMap,
true);
985 }
986
987 FileList_t procFiles, tmpIntermediateFiles;
988
989 FileList_t::const_iterator filesEnd =
allFiles.end();
990 FileList_t::const_iterator fi =
allFiles.begin();
991
993 std::string tmpInputFile("");
994 std::string tmpOutputFile("");
995
996
997 while (fi != filesEnd) {
998
999 procFiles.push_back(*fi);
1001 ++fi;
1002 if (counter % nFilesAtOnce == 0 || fi == filesEnd) {
1003 std::ostringstream nameStream;
1004 nameStream <<
"tmp_merge_" <<
counter <<
".root";
1005 tmpOutputFile = nameStream.str();
1006 tmpIntermediateFiles.push_back(tmpOutputFile);
1008 if (stat)
return stat;
1009 procFiles.clear();
1010 }
1011 }
1012
1013 int stat=
mergeFiles(outFileName, tmpIntermediateFiles,fileLBMap,
true);
1014 if (stat)
return stat;
1015
1016 for (const auto& tmpFile : tmpIntermediateFiles) {
1019 std::cerr<<"MonitoringFile::mergeFiles: tmpFile "<<tmpFile<<" could not be removed\n";
1020 }
1021 }
1022 return 0;
1023 }
1024
1025 void MonitoringFile::printStatistics() {
1026 if (m_file == 0) {
1027 std::cerr << "MonitoringFile::printStatistics(): "
1028 << "No input file is open\n";
1029 return;
1030 }
1031
1032 DirMap_t indirmap;
1033
1034 getAllDirs(indirmap, m_file, "");
1035
1036 DirMap_t::const_iterator idirend = indirmap.end();
1037 for (DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir) {
1038 std::string idirName = idir->first;
1039
1040 GatherStatistics stat_shift(idirName);
1041 GatherStatistics stat_all(idirName);
1042
1043 loopOnHistogramsInMetadata(stat_shift, idir->second);
1044 loopOnHistograms(stat_all, idir->second);
1045
1046 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
1047 std::cout.width(80);
1048 std::cout << idirName << " ";
1049
1050 std::cout.setf(std::ios_base::right, std::ios_base::adjustfield);
1051 std::cout << " shift: ";
1052 std::cout.width(3);
1053 std::cout << stat_shift.m_nHist1D << " ";
1054 std::cout.width(5);
1055 std::cout << stat_shift.m_nHist1DBins << " ";
1056 std::cout.width(3);
1057 std::cout << stat_shift.m_nHist2D << " ";
1058 std::cout.width(7);
1059 std::cout << stat_shift.m_nHist2DBins << " ";
1060 std::cout.width(3);
1061 std::cout << stat_shift.m_nGraph << " ";
1062 std::cout.width(5);
1063 std::cout << stat_shift.m_nGraphPoints << " ";
1064
1065 std::cout << " all: ";
1066 std::cout << stat_all.m_nHist1D << " ";
1067 std::cout.width(5);
1068 std::cout << stat_all.m_nHist1DBins << " ";
1069 std::cout.width(3);
1070 std::cout << stat_all.m_nHist2D << " ";
1071 std::cout.width(7);
1072 std::cout << stat_all.m_nHist2DBins << " ";
1073 std::cout.width(3);
1074 std::cout << stat_all.m_nGraph << " ";
1075 std::cout.width(5);
1076 std::cout << stat_all.m_nGraphPoints << "\n";
1077
1078 std::cout << std::flush;
1079 }
1080 }
1081
1082 bool MonitoringFile::copyHistograms(const std::string& outFileName, const std::string& dirName) {
1084
1085
1086
1087 if (m_file == 0) {
1088 std::cerr << "MonitoringFile::copyHistograms(): "
1089 << "No input file is open\n";
1090 return false;
1091 }
1092
1093 DirMap_t indirmap;
1094 DirMap_t reducedmap;
1095 DirMap_t outdirmap;
1096
1097 if (dirName != "all") {
1098 TKey* dkey =
getObjKey(m_file, dirName);
1099 if (dkey == 0) {
1100 std::cerr << "MonitoringFile::copyHistograms(): "
1101 <<
"Directory \'" <<
dirName <<
"\' not found in input file\n";
1102 return false;
1103 }
1104
1105 TDirectory* fromDir = dynamic_cast<TDirectory*>(dkey->ReadObj());
1106
1107 DirMap_t::value_type dirmapVal(dirName, fromDir);
1108 indirmap.insert(std::move(dirmapVal));
1109 } else {
1110 std::cout << "Building list of all TDirectories in file...\n" << std::flush;
1111 getAllDirs(indirmap, m_file, "");
1112 }
1113
1114 DirMap_t::const_iterator idirend = indirmap.end();
1115 for (DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir) {
1116
1117 std::string idirName = idir->first;
1118 std::cout << "Checking " << idirName << "\n" << std::flush;
1119
1120
1121
1122
1123
1124
1125
1126 if (!dirHasHistogramsInMetadata(idir->second)) {
1127 continue;
1128 }
1129
1130 reducedmap.insert(*idir);
1131 }
1132
1135 std::cerr << "MonitoringFile::copyHistograms(): "
1136 << "Output file not opened\n";
1137 return false;
1138 }
1139
1140 idirend = reducedmap.end();
1141 for (DirMap_t::const_iterator idir = reducedmap.begin(); idir != idirend; ++idir) {
1142
1143 std::string idirName = idir->first;
1144 std::cout << "Processing " << idirName << "\n" << std::flush;
1145
1146 TDirectory* toDir = createDir(outdirmap,
outfile.get(),
"", idirName);
1147 if (toDir == 0) {
1148 std::cerr << "MonitoringFile::copyHistograms(): "
1149 << "Directory \'" << idirName << "\' not created in output file\n";
1150 return false;
1151 }
1152
1153 CopyHistogram copyFcn(toDir, idirName);
1154
1155 loopOnHistogramsInMetadata(copyFcn, idir->second);
1156 }
1157
1159
1160 return true;
1161 }
1162
1163 std::string MonitoringFile::getHanResults(const std::string& hanResultsDir, const std::string& input, const std::string& hcfg,
1164 const std::string& hcfg_lowStat, const std::string& hcfg_medStat) {
1165
1166
1167 std::cout << "\nUsing han configurations:\n"
1168 <<
" entire run: " <<
hcfg <<
"\n"
1169 << " low stat interval: " << hcfg_lowStat << "\n"
1170 << " medium stat interval: " << hcfg_medStat << "\n\n"
1171 << std::flush;
1172
1174 if (infile == 0) {
1175 std::cerr << "MonitoringFile::getHanResults(): "
1176 <<
"Cannot open input file \"" <<
input <<
"\"\n";
1177 return "";
1178 }
1179
1180 std::vector<std::string> run_dirs;
1181 std::vector<std::string> lowStat_dirs;
1182 std::vector<std::string> medStat_dirs;
1183
1184 TIter next_run(
infile->GetListOfKeys());
1185 TKey* key_run(0);
1186 while ((key_run = dynamic_cast<TKey*>(next_run())) != 0) {
1187 TObject* obj_run = key_run->ReadObj();
1188 TDirectory* tdir_run = dynamic_cast<TDirectory*>(obj_run);
1189 if (tdir_run != 0) {
1190 std::string tdir_run_name(tdir_run->GetName());
1191 if (tdir_run_name.find("run") != std::string::npos) {
1192 run_dirs.push_back(tdir_run_name);
1193 TIter next_minutes(tdir_run->GetListOfKeys());
1194 TKey* key_minutes(0);
1195 while ((key_minutes = dynamic_cast<TKey*>(next_minutes())) != 0) {
1196 TObject* obj_minutes = key_minutes->ReadObj();
1197 TDirectory* tdir_minutes = dynamic_cast<TDirectory*>(obj_minutes);
1198 if (tdir_minutes != 0) {
1199 std::string tdir_minutes_name(tdir_minutes->GetName());
1200 if (tdir_minutes_name.find("lowStat") != std::string::npos) {
1201 lowStat_dirs.push_back(tdir_run_name + '/' + tdir_minutes_name);
1202 } else if (tdir_minutes_name.find("medStat") != std::string::npos) {
1203 medStat_dirs.push_back(tdir_run_name + '/' + tdir_minutes_name);
1204 }
1205 }
1206 delete obj_minutes;
1207 }
1208 }
1209 }
1210 delete obj_run;
1211 }
1212
1214
1216
1218 std::vector<std::string>::const_iterator dirs_end;
1219 std::vector<std::string>::const_iterator
dir;
1220
1221 dirs_end = run_dirs.end();
1222 for (dir = run_dirs.begin(); dir != dirs_end; ++dir) {
1223 const std::string& tdir_run_name = *
dir;
1224 std::string han_output_run =
hanResultsDir +
'/' + tdir_run_name +
"_han.root";
1225 std::cout <<
"Calling han( " <<
hcfg <<
", " <<
input <<
", " << tdir_run_name <<
", " << han_output_run <<
" ):\n" << std::flush;
1226 han.Analyze(hcfg, input, han_output_run, tdir_run_name);
1227 std::cout << "\n";
1228 fileList += han_output_run +
" " + tdir_run_name +
"\n";
1229 }
1230
1231 dirs_end = lowStat_dirs.end();
1232 for (dir = lowStat_dirs.begin(); dir != dirs_end; ++dir) {
1233 const std::string& tdir_minutes_path = *
dir;
1234
1235 std::string tdir_minutes_underscore = tdir_minutes_path;
1236 std::string::size_type tdir_minutes_i = tdir_minutes_underscore.find('/');
1237 tdir_minutes_underscore.replace(tdir_minutes_i, 1, "_");
1238
1239 std::string han_output_lowStat =
hanResultsDir +
'/' + tdir_minutes_underscore +
"_han.root";
1240 std::cout << "Running han, writing to " << han_output_lowStat << ":\n" << std::flush;
1241 han.Analyze(hcfg_lowStat, input, han_output_lowStat, tdir_minutes_path);
1242 std::cout << "\n";
1243 std::string subdirname(tdir_minutes_path, tdir_minutes_i + 1, std::string::npos);
1244 std::string
dirname(tdir_minutes_path, 0, tdir_minutes_i);
1245 fileList += han_output_lowStat +
" " + subdirname +
" " +
dirname +
" " + subdirname +
"\n";
1246 }
1247
1248 dirs_end = medStat_dirs.end();
1249 for (dir = medStat_dirs.begin(); dir != dirs_end; ++dir) {
1250 const std::string& tdir_minutes_path = *
dir;
1251
1252 std::string tdir_minutes_underscore = tdir_minutes_path;
1253 std::string::size_type tdir_minutes_i = tdir_minutes_underscore.find('/');
1254 tdir_minutes_underscore.replace(tdir_minutes_i, 1, "_");
1255
1256 std::string han_output_medStat =
hanResultsDir +
'/' + tdir_minutes_underscore +
"_han.root";
1257 std::cout << "Running han, writing to " << han_output_medStat << ":\n" << std::flush;
1258 han.Analyze(hcfg_medStat, input, han_output_medStat, tdir_minutes_path);
1259 std::cout << "\n";
1260 std::string subdirname(tdir_minutes_path, tdir_minutes_i + 1, std::string::npos);
1261 std::string
dirname(tdir_minutes_path, 0, tdir_minutes_i);
1262 fileList += han_output_medStat +
" " + subdirname +
" " +
dirname +
" " + subdirname +
"\n";
1263 }
1264
1266 }
1267
1268 void MonitoringFile::printHanConfig() {
1269 if (m_file == 0) {
1270 std::cerr << "MonitoringFile::printHanConfig(): "
1271 << "No input file is open\n";
1272 return;
1273 }
1274
1275 DirMap_t indirmap;
1276
1277 getAllDirs(indirmap, m_file, "");
1278
1279 std::string
indent, indent_p, indent_c;
1280 std::string idirName_p;
1281 DirMap_t::const_iterator idirend = indirmap.end();
1282 for (DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir) {
1283 std::string idirName = idir->first;
1284 std::string::size_type shortNameIndex = idirName.rfind('/');
1285 std::string
shortName = idirName.substr(shortNameIndex + 1, std::string::npos);
1286
1287 std::string::size_type fsIndex = idirName.find('/');
1288 std::string shortPath;
1289 if (fsIndex != shortNameIndex)
1290 shortPath = idirName.substr(fsIndex + 1, shortNameIndex);
1291 else
1292 shortPath = idirName.substr(fsIndex + 1, std::string::npos);
1293
1294 std::cout << idirName << "\n";
1295 std::cout << shortPath <<
", " <<
shortName <<
"\n";
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330 }
1331 }
1332
1333 std::string MonitoringFile::getIndentation(const std::string& pathName, const std::string& leadingSpace) {
1334 std::string space = leadingSpace;
1335 std::string::size_type
i =
pathName.find_first_of(
'/');
1336 if (i != std::string::npos) {
1337 std::string subPath(pathName, i + 1, std::string::npos);
1338 space += " ";
1339 return getIndentation(subPath, space);
1340 }
1341 return space;
1342 }
1343
1344 std::string MonitoringFile::FindCommon(const std::string& name1, const std::string& name2) const {
1351 } else {
1353 }
1354 }
1356 }
1357
1358
1359
1360
1361
1362 MonitoringFile::CopyHistogram::CopyHistogram(TDirectory * target,
const std::string& dirName) : m_target(
target), m_dirName(
dirName), m_metadata(0) {
1363 m_metadata = new TTree("metadata", "Monitoring Metadata");
1364 m_metadata->SetDirectory(0);
1365 m_metadata->Branch("Name", (void*)nullptr, "Name/C");
1366 m_metadata->Branch("Interval", (void*)nullptr, "Interval/C");
1367 m_metadata->Branch("TriggerChain", (void*)nullptr, "TriggerChain/C");
1368 m_metadata->Branch("MergeMethod", (void*)nullptr, "MergeMethod/C");
1369 }
1370
1371 MonitoringFile::CopyHistogram::~CopyHistogram() {
1372 m_target->cd();
1373 m_metadata->SetDirectory(m_target);
1374 m_metadata->Write();
1375 delete m_metadata;
1376 }
1377
1378 bool MonitoringFile::CopyHistogram::execute(TH1 * hist) {
1379 m_target->cd();
1380 hist->SetDirectory(m_target);
1382
1383 return true;
1384 }
1385
1386 bool MonitoringFile::CopyHistogram::execute(TGraph * graph) {
1387 m_target->cd();
1388 graph->Write();
1389
1390 return true;
1391 }
1392
1393 bool MonitoringFile::CopyHistogram::execute(TEfficiency * eff) {
1394 m_target->cd();
1396 return true;
1397 }
1398
1399 void MonitoringFile::CopyHistogram::fillMD(const MetaData& md) {
1400 std::string
name(md.name);
1402 std::string
chain(md.chain);
1403 std::string
merge(md.merge);
1404 m_metadata->SetBranchAddress(
"Name",
name.data());
1405 m_metadata->SetBranchAddress(
"Interval",
interval.data());
1406 m_metadata->SetBranchAddress(
"TriggerChain",
chain.data());
1407 m_metadata->SetBranchAddress(
"MergeMethod",
merge.data());
1408 m_metadata->Fill();
1409 }
1410
1411 bool MonitoringFile::CopyHistogram::executeMD(TH1 * hist, const MetaData& md) {
1412 m_target->cd();
1413 hist->SetDirectory(m_target);
1415
1416 fillMD(md);
1417
1418 return true;
1419 }
1420
1421 bool MonitoringFile::CopyHistogram::executeMD(TGraph * graph, const MetaData& md) {
1422 m_target->cd();
1423 graph->Write();
1424
1425 fillMD(md);
1426
1427 return true;
1428 }
1429
1430 bool MonitoringFile::CopyHistogram::executeMD(TEfficiency * eff, const MetaData& md) {
1431 m_target->cd();
1433 fillMD(md);
1434 return true;
1435 }
1436
1437 MonitoringFile::GatherStatistics::GatherStatistics(const std::string& dirName)
1438 : m_dirName(
dirName), m_nHist1D(0), m_nHist1DBins(0), m_nGraph(0), m_nGraphPoints(0), m_nHist2D(0), m_nHist2DBins(0) {}
1439
1440 bool MonitoringFile::GatherStatistics::execute(TH1 * hist) {
1441 TH2* hist2d =
dynamic_cast<TH2*
>(
hist);
1442 if (hist2d != 0) {
1443 ++m_nHist2D;
1444 m_nHist2DBins += (hist2d->GetNbinsX() * hist2d->GetNbinsY());
1445 return true;
1446 }
1447 ++m_nHist1D;
1448 m_nHist1DBins +=
hist->GetNbinsX();
1449 return true;
1450 }
1451
1452 bool MonitoringFile::GatherStatistics::execute(TGraph * graph) {
1453 ++m_nGraph;
1454 m_nGraphPoints += graph->GetMaxSize();
1455 return true;
1456 }
1457
1458 bool MonitoringFile::GatherStatistics::execute(TEfficiency * eff) {
1459 ++m_nEfficiency;
1460
1461 TH1* h_total =
eff->GetCopyPassedHisto();
1462 TH2* h_total2D = dynamic_cast<TH2*>(h_total);
1463
1464 if (h_total2D != 0) {
1465 m_nEfficiencyBins += (h_total2D->GetNbinsX() * h_total2D->GetNbinsY());
1466 return true;
1467 } else {
1468 m_nEfficiencyBins += h_total->GetNbinsX();
1469 return true;
1470 }
1471 }
1472
1473 MonitoringFile::GatherNames::GatherNames() {}
1474
1475 bool MonitoringFile::GatherNames::execute(TH1 * hist) {
1476 m_names.push_back(std::string(
hist->GetName()));
1477 return true;
1478 }
1479
1480 bool MonitoringFile::GatherNames::execute(TGraph * graph) {
1481 m_names.push_back(std::string(graph->GetName()));
1482 return true;
1483 }
1484
1485 bool MonitoringFile::GatherNames::execute(TEfficiency * eff) {
1486 m_names.push_back(std::string(
eff->GetName()));
1487 return true;
1488 }
1489
1490 void MonitoringFile::clearData() {
1492
1493 delete m_file;
1494 m_file = 0;
1495 m_fileCompressionLevel = 1;
1496 m_doTiming = false;
1497 }
1498
1499 bool MonitoringFile::dirHasHistogramsInMetadata(TDirectory * dir) {
1501
1502 TKey* mdKey =
dir->FindKey(
"metadata");
1503 if (mdKey == 0) {
1504 return false;
1505 }
1506
1507 TTree* md = dynamic_cast<TTree*>(mdKey->ReadObj());
1508 if (md == 0) {
1509 return false;
1510 }
1511
1512 int nEntries = int(md->GetEntries());
1513
1514 if (nEntries > 0) {
1515 try {
1516 md->GetEntry(0);
1517 } catch (const std::exception& e) {
1518 std::cerr <<
"Exception: \"" <<
e.what() <<
"\" in directory \"" <<
dir->GetName() <<
"\"\n" << std::flush;
1519 return false;
1520 }
1521
1522 return true;
1523 }
1524
1525 return false;
1526 }
1527
1528 void MonitoringFile::loopOnHistograms(HistogramOperation & fcn, TDirectory * dir) {
1529 TIter
next(
dir->GetListOfKeys());
1531 while ((key =
dynamic_cast<TKey*
>(
next())) != 0) {
1532 TObject*
obj =
key->ReadObj();
1536 if ((
h =
dynamic_cast<TH1*
>(obj))) {
1538 } else if ((g = dynamic_cast<TGraph*>(obj))) {
1539 fcn.execute(g);
1540 } else if ((e = dynamic_cast<TEfficiency*>(obj))) {
1541 fcn.execute(e);
1542 }
1544 }
1545 }
1546
1547 bool MonitoringFile::loopOnHistogramsInMetadata(HistogramOperation & fcn, TDirectory * dir) {
1549 TKey* mdKey =
dir->FindKey(
"metadata");
1550 if (mdKey == 0) {
1551 return false;
1552 }
1553
1554 TTree* md = dynamic_cast<TTree*>(mdKey->ReadObj());
1555 if (md == 0) {
1556 return false;
1557 }
1558
1559 TKey* i_key;
1560
1562 TTreeReaderArray<char> i_name(reader, "Name");
1563 TTreeReaderArray<char> i_interval(reader, "Interval");
1564 TTreeReaderArray<char> i_chain(reader, "TriggerChain");
1565 TTreeReaderArray<char> i_merge(reader, "MergeMethod");
1566
1568 const std::string nameStr(static_cast<char*>(i_name.GetAddress()));
1570 i_key =
dir->FindKey(
static_cast<char*
>(i_name.GetAddress()));
1571 if (i_key == 0) {
1572 std::cerr << "MonitoringFile::loopOnHistogramsInMetadata(): "
1573 << "No \'" << nameStr << "\' object found\n";
1574 return false;
1575 }
1576 MetaData md(nameStr, static_cast<char*>(i_interval.GetAddress()), static_cast<char*>(i_chain.GetAddress()), static_cast<char*>(i_merge.GetAddress()));
1577 TObject*
obj = i_key->ReadObj();
1578 TH1*
h =
dynamic_cast<TH1*
>(
obj);
1580 fcn.executeMD(
h, md);
1581 } else {
1582 TGraph*
g =
dynamic_cast<TGraph*
>(
obj);
1583 if (g != 0) {
1584 fcn.executeMD(g, md);
1585 }
1586 }
1588 }
1589
1590 delete md;
1591
1592 return true;
1593 }
1594
1595 bool MonitoringFile::setListFromFile(std::vector<std::string> & filelist, const std::string& listFileName) {
1596 using namespace std;
1597
1599
1600 ifstream listfile(listFileName.c_str());
1601 if (!listfile) {
1602 cerr << "MonitoringFile::setListFromFile(): "
1603 << "cannot read from file: " << listFileName << "\n";
1604 return false;
1605 }
1606
1610 while (getline(listfile, line)) {
1611 istringstream linestream(line);
1612 while (linestream.get(c)) {
1613 if (!isspace(c)) {
1614
1615 if (c == '#') {
1616 break;
1617 }
1618
1619 linestream.putback(c);
1621 if (!linestream) {
1622 cerr << "MonitoringFile::setListFromFile(): "
1623 <<
"badly formatted line: " <<
line <<
"\n";
1624 break;
1625 }
1626
1628 }
1629 }
1630 }
1631
1632 return true;
1633 }
1634
1635 int MonitoringFile::mergeLBintervals(const std::string& inFilename) {
1636
1637 std::cout << "Running mergeLBintervals on " << inFilename << std::endl;
1638
1639 std::unique_ptr<TFile>
f(TFile::Open(inFilename.c_str(),
"UPDATE"));
1640 if (!f) {
1641 std::cout << "ERROR, could not open file " << inFilename << " for update" << std::endl;
1642 return -1;
1643 }
1644 std::string runDirName;
1645 const std::regex runDirPattern("run_[0-9]*");
1646 TIter
next(
f->GetListOfKeys());
1648 while ((key = (TKey*)
next())) {
1649 const char*
name =
key->GetName();
1650 if (std::regex_match(name, runDirPattern)) {
1651 if (runDirName.size() > 0) {
1652 std::cout <<
"ERROR More than one run_XXX directory found! Ignoring " <<
name << std::endl;
1653 } else
1655 }
1656 break;
1657 }
1658
1659 TDirectory* runDir =
f->GetDirectory(runDirName.c_str());
1660 const auto mapping = buildLBToIntervalMap(runDir);
1661
1662 if (s_dbg.getLvl() == VERBOSE) {
1663 std::cout << "LB directory mapping:" << std::endl;
1664 for (const auto& i1 : mapping) {
1665 std::cout << i1.first;
1666 for (const auto& i2 : i1.second) {
1667 std::cout << "\t" << i2 << std::endl;
1668 }
1669 }
1670 }
1671
1672 for (const auto& [outDir, inDIrs] : mapping) {
1673 int stat=mergeLB_processLBinterval(
f.get(), inDIrs, outDir);
1674 if (stat)
return stat;
1675 }
1676
1678 f.reset(TFile::Open(inFilename.c_str(),
"UPDATE"));
1679 runDir =
f->GetDirectory(runDirName.c_str());
1680
1681 std::cout << "merging lowStat_LB dirs into run-dir" << std::endl;
1682 std::vector<std::string> lowStatDirs;
1683 for (TObject* oKey : *runDir->GetListOfKeys()) {
1684 TKey*
key =
static_cast<TKey*
>(oKey);
1685 const std::string
name =
key->GetName();
1686 const std::string classname =
key->GetClassName();
1687 if (classname.starts_with(
"TDirectory") and
name.starts_with(
"lowStat_LB")) {
1688 lowStatDirs.push_back(runDirName + "/" + name);
1689 s_dbg(VERBOSE, "Found input: " + runDirName + "/" + name);
1690 }
1691 }
1692
1693 int stat=mergeLB_processLBinterval(
f.get(), lowStatDirs, runDirName);
1694
1697 }
1698
1699 std::map<std::string, std::vector<std::string>> MonitoringFile::buildLBToIntervalMap(TDirectory * runDir) {
1700
1701 std::map<std::string, std::vector<std::string>> ranges;
1702
1703
1704 const std::string runDirName = runDir->GetName();
1705 for (TObject* oKey : *runDir->GetListOfKeys()) {
1706 TKey*
key =
static_cast<TKey*
>(oKey);
1707 const std::string
name =
key->GetName();
1708 const std::string classname =
key->GetClassName();
1709 if (!classname.starts_with("TDirectory"))
1710 continue;
1711 if (
name.starts_with(
"lb_")) {
1713 try {
1715 } catch (std::invalid_argument& e) {
1716 std::cout <<
"ERROR, unexpected directory name " <<
name <<
". Can't parse lb number" << std::endl;
1717 std::cout <<
e.what() << std::endl;
1718 continue;
1719 }
1720
1722 const std::string lbString = runDirName + "/lowStat_LB" + std::to_string(lbBase) + "-" + std::to_string(lbBase + 19);
1723 ranges[lbString].push_back(runDirName + "/" + name);
1724 }
1725 }
1726 return ranges;
1727 }
1728
1729 int MonitoringFile::mergeLB_processLBinterval(TFile *
file,
const std::vector<std::string>& inputDirNames,
const std::string& outputDirName) {
1730
1731 TDirectory* outDir =
file->GetDirectory(outputDirName.c_str());
1732 if (!outDir) {
1733 outDir =
file->mkdir(outputDirName.c_str());
1734 }
1735 if (!outDir) {
1736 std::cout <<
"ERROR, can't obtain nor create directory " << outputDirName <<
" in file " <<
file->GetName() << std::endl;
1737 return -1;
1738 }
1739
1741 hc.addDirExclusion(m_mergeMatchDirRE);
1742 hc.addHistExclusion(m_mergeMatchHistoRE);
1743
1744 for (const std::string& inDirName : inputDirNames) {
1745 TDirectory* inDir =
file->GetDirectory(inDirName.c_str());
1746 hc.addDirectory(inDir, outputDirName);
1747 }
1748 if (hc.size() == 0) {
1749 std::cout << "mergeLB_processLBinterval: No new objects found for " << outputDirName << std::endl;
1750 } else {
1751 hc.write();
1752 }
1753 return 0;
1754 }
1755
1756 bool MonitoringFile::CheckHistogram(TFile * f, const char* HistoName) {
1757 std::unique_ptr<TObject>
obj(
f->Get(HistoName));
1759
1760 return false;
1761 } else
1762 return true;
1763 }
1764
1765 int MonitoringFile::getDebugLevel() {
1766 return s_dbg.getLvl();
1767 }
1768 void MonitoringFile::setDebugLevel(int level) {
1769 s_dbg.setLvl((debugLevel_t)(level));
1770 }
1771 void MonitoringFile::doTiming() {
1772 m_doTiming = true;
1773 }
1774
1775
1776 void MonitoringFile::setCheckEquality(
bool value) {dqutils::s_checkEquality=
value;}
1777 std::atomic<int> MonitoringFile::m_fileCompressionLevel = 1;
1778 bool MonitoringFile::m_doTiming = false;
1779 std::unordered_map<std::string, std::clock_t> MonitoringFile::m_cpuPerHistogram;
1780
1781 std::string MonitoringFile::getPath(TDirectory * dir) {
1782
1783 std::string
path =
dir->GetPath();
1784 if (
path.find(
':') != std::string::npos)
1786
1788 }
1789
1790}
const boost::regex re(r_e)
void defaultMerge(TObject *a, const TObject *b)
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
Header file for AthHistogramAlgorithm.
static void merge_identical(TH1 &a, const TH1 &b)
static void merge_weightedAverage(TH1 &a, const TH1 &b)
static void merge_RMS(TH1 &a, const TH1 &b)
static void merge_eventSample(TH2 &a, const TH2 &b)
static void merge_RMSpercentDeviation(TH1 &a, const TH1 &b)
static void merge_lowerLB(TH1 &a, const TH1 &b)
static void merge_weightedEff(TH1 &a, const TH1 &b)
static void merge_perBinEffPerCent(TH1 &a, const TH1 &b)
static void merge_Rebinned(TH1 &a, TH1 &b)
void(* mergeMethod)(TObject *a, const TObject *b)
histPerDir_t(const std::string &nameIn, TObject *objIn, TTree *md, bool dbg=false)
std::map< std::string, histDir_t > m_data
void addDirectory(TDirectory *dir, const std::string &dirName)
histCollection(bool debug=false)
std::vector< std::string > files
file names and file pointers
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
std::unique_ptr< SampleLocal > mergeFiles(const Sample &sample, const std::string &location, bool overwrite)
merge all the files in the sample into a single file in the given location
path
python interpreter configuration --------------------------------------—
reader
read the goodrunslist xml file(s)
TKey * getObjKey(TDirectory *dir, const std::string &path)
std::map< std::string, std::set< std::string > > fileLBMap_t
filelist
print ("Checking files %s..." % fullfile)
merge(input_file_pattern, output_file)
Merge many input LHE files into a single output file.
DataModel_detail::iterator< DVL > remove(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, const T &value)
Specialization of remove for DataVector/List.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::vector< histPerDir_t > histos
std::string dirname(std::string name)