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