ATLAS Offline Software
Loading...
Searching...
No Matches
HanOutput.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <TDirectory.h>
8#include <TEfficiency.h>
9#include <TFile.h>
10#include <TGraph.h>
11#include <TH1.h>
12#include <TKey.h>
13#include <TList.h>
14#include <TNamed.h>
15#include <TObjArray.h>
16#include <TObjString.h>
17#include <TObject.h>
18#include <TROOT.h>
19#include <string.h> // strncmp()
20
21#include <boost/algorithm/string.hpp>
22#include <iomanip>
23#include <iostream>
24#include <map>
25#include <sstream>
26
29#include "dqm_core/OutputListener.h"
30#include "dqm_core/Parameter.h"
31#include "dqm_core/Region.h"
32#include "dqm_core/Result.h"
33#include "dqm_core/exceptions.h"
34
35namespace
36{
37
38 std::string StatusToStr(const dqm_core::Result::Status& status);
39}
40
41namespace dqi
42{
43
44 bool setNameGeneral(TObject* obj, const std::string& name)
45 {
46 if (obj != 0)
47 {
48 // some special cases, to avoid interpreter
49 if (TH1* h = dynamic_cast<TH1*>(obj))
50 {
51 h->SetName(name.c_str());
52 return true;
53 }
54 else if (TObjArray* a = dynamic_cast<TObjArray*>(obj))
55 {
56 a->SetName(name.c_str());
57 return true;
58 }
59 else if (TGraph* g = dynamic_cast<TGraph*>(obj))
60 {
61 g->SetName(name.c_str());
62 return true;
63 }
64 else if (TEfficiency* e = dynamic_cast<TEfficiency*>(obj))
65 {
66 e->SetName(name.c_str());
67 return true;
68 }
69 else
70 {
71 TClass* kl = obj->IsA();
72 TMethod* klm = kl->GetMethod("SetName", "\"Reference\"");
73 if (!klm)
74 {
75 std::cerr << "Error: attempt to change object name to " << name << " failed as its name is not settable"
76 << std::endl;
77 }
78 else
79 {
80 std::cout << "Manually doing cast for " << name << " of class " << kl->GetName() << std::endl;
81 obj->Execute("SetName", ("\"" + name + "\"").c_str());
82 return true;
83 }
84 }
85 }
86 return false;
87 }
88
89 const int HanOutput::Result::s_charArrSize = 10;
90
91 // *********************************************************************
92 // Public Methods
93 // *********************************************************************
94
95 HanOutput::HanOutput(const std::string& rootFileName, DQOutputMap_t* outMap, TSeqCollection* outList)
96 : m_fileName(rootFileName),
97 m_file(TFile::Open(rootFileName.c_str(), "RECREATE")),
98 m_retainUnpubData(false),
99 m_config(0),
100 m_input(0)
101 {
102 m_outputMap = outMap;
103 m_outputList = outList;
104 if (m_file.get() == 0)
105 {
106 std::cerr << "File not writable: " << rootFileName << "\n";
107 }
108 }
109
111 {
112 DQResultMap_t::const_iterator rend = m_dqResults.end();
113 for (DQResultMap_t::const_iterator i = m_dqResults.begin(); i != rend; ++i)
114 {
115 dqm_core::Result* result = i->second;
116 delete result;
117 }
118 m_file->Close();
119 }
120
121 void HanOutput::addListener(const std::string& name, dqm_core::OutputListener* listener)
122 {
123 dqm_core::Region* region = dynamic_cast<dqm_core::Region*>(listener);
124 if (region == 0) return;
125
126 DQParMap_t::const_iterator i = m_dqPars.find(name);
127 if (i != m_dqPars.end())
128 {
129 if (i->second != region)
130 {
131 std::cerr << "Attempt to add " << name << " twice; ignoring" << std::endl;
132 }
133 else
134 {
135 return;
136 }
137 }
138
139 DQParMap_t::value_type dqParVal(name, region);
140 m_dqPars.insert(std::move(dqParVal));
141
142 DQRegMap_t::value_type dqRegVal(region, name);
143 m_dqRegs.insert(std::move(dqRegVal));
144
145 m_unpublishedDQPars.insert(name);
146 }
147
148 void HanOutput::addListener(const dqm_core::Parameter& parameter, dqm_core::OutputListener* listener)
149 {
150 addListener(parameter.getName(), listener);
151 }
152
153 void HanOutput::publishResult(const std::string& name, const dqm_core::Result& result)
154 {
155 // std::cout << "Publish " << name << std::endl;
156 delete m_dqResults[name];
157 m_dqResults[name] = result.clone();
158
159 DQParSet_t::iterator dqpari = m_unpublishedDQPars.find(name);
160 if (dqpari != m_unpublishedDQPars.end() && !m_retainUnpubData)
161 {
162 m_unpublishedDQPars.erase(dqpari);
163 }
164
166 {
167 DQParMap_t::const_iterator i = m_dqPars.find(name);
168 if (i != m_dqPars.end())
169 {
170 dqm_core::Region* parent = i->second;
171 dqm_core::OutputListener* plistener = parent;
172 plistener->handleResult(name, result);
173 }
174 }
175 }
176
178 {
179 // store regex lists
180 DQOutputMap_t tmpRegex;
181 DQParSet_t::const_iterator regexEnd = m_regexlist.end();
182 for (DQParSet_t::const_iterator regex = m_regexlist.begin(); regex != regexEnd; ++regex)
183 {
184 TSeqCollection* resultList = (*m_outputMap)[*regex];
185 if (resultList == 0)
186 {
187 std::cerr << "Can't find original list for regex???" << std::endl;
188 }
189 else
190 {
191 tmpRegex.insert(DQOutputMap_t::value_type(*regex, resultList));
192 (*m_outputMap).erase(*regex);
193 DQParMap_t::const_iterator i = m_dqPars.find(*regex);
194 if (i != m_dqPars.end())
195 {
196 dqm_core::Region* parent = i->second;
197
198 std::string parentName = parent->getName();
199 // just remove, don't delete
200 static_cast<TSeqCollection*>((*m_outputMap)[parentName])->Remove(resultList);
201 }
202 }
203 }
204
205 // replay results
206 DQResultMap_t::const_iterator rEnd = m_dqResults.end();
207 for (DQResultMap_t::const_iterator r = m_dqResults.begin(); r != rEnd; ++r)
208 {
209 const std::string name(r->first);
210 const dqm_core::Result& result(*(r->second));
211
212 std::string parentName("top_level");
213 DQParMap_t::const_iterator i = m_dqPars.find(name);
214
215 if (i != m_dqPars.end())
216 {
217 dqm_core::Region* parent = i->second;
218 parentName = parent->getName();
219 }
220 // copy-paste ENDS here
221
222 TSeqCollection* resultList = (*m_outputMap)[name];
223 std::string parname(name);
224 std::string storename(name);
225
226 if (resultList == NULL)
227 {
228 // is regex?
229 bool isRegex = false;
230 std::string extra;
231 for (DQParSet_t::const_iterator regex = m_regexlist.begin(); regex != regexEnd; ++regex)
232 {
233 std::string::size_type regexlen = regex->length();
234 if (*regex + "_" == name.substr(0, regexlen + 1))
235 {
236 isRegex = true;
237 parname = *regex;
238 std::string::size_type atsign = regex->rfind('@');
239 if (atsign != std::string::npos)
240 {
241 extra = regex->substr(atsign, std::string::npos);
242 }
243 storename = name.substr(regexlen + 1, std::string::npos);
244 break;
245 }
246 }
247 if (isRegex)
248 {
249 if (m_input == NULL)
250 {
251 std::cerr << "WARNING: setInput() has not been set; cannot publish regex results" << std::endl;
252 continue;
253 }
254 resultList = static_cast<TSeqCollection*>(tmpRegex[parname]->Clone());
255 (*m_outputMap)[storename + extra] = resultList;
256 DQParMap_t::const_iterator i = m_dqPars.find(parname);
257 if (i == m_dqPars.end()) {
258 std::cerr << "WARNING: Can't find parname in m_dqPars" << std::endl;
259 continue;
260 }
261 parentName = i->second->getName();
262 bool use_full_name = false;
263 if (m_config)
264 {
265 std::unique_ptr<const HanConfigAssessor> a(m_config->GetAssessor(parentName, parname));
266 if (a.get())
267 {
268 std::string store_using_path;
269 const HanConfigParMap* hcpm = a->GetAnnotation("store_using_path");
270 if (hcpm)
271 {
272 store_using_path.assign(hcpm->GetValue());
273 }
274 boost::algorithm::to_lower(store_using_path);
275 if (store_using_path == "1" || store_using_path == "yes" || store_using_path == "true")
276 {
277 use_full_name = true;
278 }
279 }
280 }
281 if (use_full_name)
282 {
283 resultList->SetName((boost::algorithm::replace_all_copy(storename, "/", "_") + extra + "_").c_str());
284 }
285 else
286 {
287 resultList->SetName((storename + extra + "_").c_str());
288 }
289 dynamic_cast<TSeqCollection*>((*m_outputMap)[parentName])->Add(resultList);
290 TKey* key = getObjKey(m_input, storename);
291 if (key != 0)
292 {
293 const char* className = key->GetClassName();
294 if ((strncmp(className, "TH", 2) == 0) || (strncmp(className, "TGraph", 6) == 0) ||
295 (strncmp(className, "TProfile", 8) == 0) || (strncmp(className, "TEfficiency", 11) == 0))
296 {
297 TNamed* transobj = dynamic_cast<TNamed*>(key->ReadObj());
298 if (transobj != NULL)
299 {
300 HanHistogramLink* hhl = new HanHistogramLink(m_input, storename);
301 if (use_full_name)
302 {
303 hhl->SetName((boost::algorithm::replace_all_copy(storename, "/", "_") + extra).c_str());
304 }
305 else
306 {
307 hhl->SetName((std::string(transobj->GetName()) + extra).c_str());
308 }
309 // transobj->SetName((std::string(transobj->GetName()) + extra).c_str());
310 // resultList->Add(transobj);
311 resultList->Add(hhl);
312 }
313 else
314 {
315 std::cerr << "TNamed* cast failed for " << storename << std::endl;
316 }
317 }
318 }
319 else
320 {
321 std::cout << "key is NULL" << std::endl;
322 }
323 }
324 else
325 {
326 std::cerr << "WARNING: Unable to find mapping for " << name << std::endl;
327 continue;
328 }
329 }
330
331
332 if (resultList)//ensure resultList is not null before dereference
333 {
334 resultList = dynamic_cast<TSeqCollection*>(resultList->FindObject("Results"));
335 }
336 //check dynamic cast
337 if (resultList == nullptr)
338 {
339 std::cerr << "Warning: no result list found associated with '" << name << "'\n";
340 continue;
341 }
342
343
344 resultList->Add(newTObjArray("Status", new TObjString(StatusToStr(result.status_).c_str()), 1));
345
346 // iterate through the tags
347 std::map<std::string, double>::const_iterator iter = result.tags_.begin();
348 for (; iter != result.tags_.end(); ++iter)
349 {
350 std::ostringstream tagval;
351 tagval << std::setprecision(4) << iter->second;
352 resultList->Add(newTObjArray(iter->first.c_str(), new TObjString(tagval.str().c_str()), 1));
353 }
354
355 // if there's an output object from the algorithm, include a clone
356 TObject* resultobj = result.getObject();
357 if (resultobj != 0)
358 {
359 TObject* resultobjclone = resultobj->Clone();
360 if (setNameGeneral(resultobj, "ResultObject"))
361 {
362 resultList->Add(resultobjclone);
363 }
364 else
365 {
366 std::cerr << "Discarding result object " << result.getObject()->GetName() << std::endl;
367 delete resultobjclone;
368 }
369 }
370
371 if (m_config != 0)
372 {
373 TObject* ref = m_config->GetReference(parentName, parname);
374 if (ref)
375 {
376 if (setNameGeneral(ref, "Reference"))
377 {
378 resultList->Add(ref);
379 }
380 else
381 {
382 std::cerr << "Discarding reference object " << ref->GetName() << std::endl;
383 }
384 }
385 }
386 }
387 }
388
389 void HanOutput::activate() { gROOT->cd(); }
390
391 void HanOutput::setInput(TDirectory* input) { m_input = input; }
392
393 static bool include_hist(TObject* obj) { //Check if object a hist or include hist
394 bool result = false;
395
396 if ((strncmp(obj->ClassName(), "TH", 2) == 0) || (strncmp(obj->ClassName(), "TGraph", 6) == 0) ||
397 (strncmp(obj->ClassName(), "TProfile", 8) == 0) || (strncmp(obj->ClassName(), "TEfficiency", 11) == 0))
398 {
399 return true;
400 }
401
402 TSeqCollection* tmpList{};
403 tmpList = dynamic_cast<TSeqCollection*>(obj);
404 if (tmpList != 0)
405 { //If it is collection - check, that it contains histograms or not
406 TIter nextElem(tmpList);
407 TObject* tmpobj{};
408 while ((tmpobj = nextElem()) != 0)
409 {
410 result = include_hist(tmpobj);
411 if (result == true)
412 {
413 return result;
414 }
415 }
416 }
417 return result;
418 }
419
421 TDirectory* dir, TSeqCollection* list, TFile* file, int level, int HanOutput_FileVersion)
422 {
423 TIter nextElem(list);
424 TObject* obj{};
425 TSeqCollection* tmpList{};
426
427 while ((obj = nextElem()) != 0)
428 {
429 bool delete_when_done = false;
430 HanHistogramLink* hhl = dynamic_cast<HanHistogramLink*>(obj);
431 if (hhl != 0)
432 {
433 obj = hhl->getObject();
434 if (!obj) continue;
435 delete_when_done = true;
436 if (not setNameGeneral(obj, hhl->GetName()))
437 {
438 std::cerr << "HanOutput.cxx, WriteListToDirectory : setNameGeneral failed\n";
439 delete obj;
440 continue;
441 };
442 }
443 if (strncmp(obj->GetName(), "Reference", 9) == 0 || strncmp(obj->GetName(), "ResultObject", 12) == 0)
444 {
445 dir->WriteTObject(obj);
446 if (delete_when_done) delete obj;
447 continue;
448 }
449 tmpList = dynamic_cast<TSeqCollection*>(obj);
450 if (tmpList != 0)
451 {
452 // Find last directory name
453 std::vector<std::string> dirs;
454 std::string str;
455 boost::split(dirs, tmpList->GetName(), boost::is_any_of("/"));
456 if (!dirs.empty())
457 {
458 if (dirs.back().empty()) dirs.pop_back(); // empty item if trailing "/"
459 str = dirs.back();
460 }
461
462 if (HanOutput_FileVersion == 2)
463 {
464 TString listname = tmpList->GetName();
465 if (listname == "Config" || listname == "Results")
466 {
468 //If yes - we should save them in the upper level
469 TIter nextElemConfRes(tmpList);
470 TObject* objInResultConfig;
471 while ((objInResultConfig = nextElemConfRes()) != 0)
472 {
473 if (include_hist(objInResultConfig))
474 {
475 //If the element consist of histograms
476 TSeqCollection* tmpList_ResConf{}; //it should be a collection type
477 tmpList_ResConf = dynamic_cast<TSeqCollection*>(objInResultConfig);
478 if ((tmpList_ResConf != 0) && (strncmp(tmpList_ResConf->GetName(), "TObjArray", 9) == 0))
479 { //Here is the special case. In case the object is an Array with the name "TObjArray", containing histograms,
480 //we should not only store it on the upper level, but also extract all the hists from it.
481 TIter nextEleminTObjArray(tmpList_ResConf);
482 TObject* objInTObjArray;
483 while ((objInTObjArray = nextEleminTObjArray()) != 0){
484 dir->WriteTObject(objInTObjArray);
485 }
486 tmpList->Remove(objInResultConfig); //This Array should not participate in JSON formation
487 }
488 else //If the element is histogram (or other Array, containing hist)- just store this obj in a higher level
489 {
490 dir->WriteTObject(objInResultConfig);
491 }
492 }
493 }
494 // For the rest of the content - Convert them to JSON
495 nlohmann::ordered_json j = to_JSON(tmpList);
496 // Then, save JSON to file as TObjString
497 // Convert json to string
498 std::string string = j.dump(4);
499 // Convert string to char *
500 char* cstr = new char[string.length() + 1];
501 std::strcpy(cstr, string.c_str());
502 // Write JSON to TObjString
503 TObjString string_to_tfile;
504 string_to_tfile.SetString(cstr);
505 dir->cd();
506 string_to_tfile.Write(listname);
507 delete[] cstr;
508 continue;
509 }
510 }
511
512 TDirectory* daughter;
513 if (!dir->FindKey(str.c_str()))
514 {
515 daughter = dir->mkdir(str.c_str());
516 }
517 else
518 {
519 std::cout << "Failed to make " << str << " from " << tmpList->GetName() << std::endl;
520 continue;
521 }
522 WriteListToDirectory(daughter, tmpList, file, level - 1, HanOutput_FileVersion);
523 if (level > 0)
524 {
525 file->Write();
526 delete daughter;
527 }
528 }
529 else if ((strncmp(obj->ClassName(), "TH", 2) == 0) || (strncmp(obj->ClassName(), "TGraph", 6) == 0) ||
530 (strncmp(obj->ClassName(), "TProfile", 8) == 0) || (strncmp(obj->ClassName(), "TEfficiency", 11) == 0))
531 {
532 dir->GetMotherDir()->WriteTObject(obj);
533 }
534 else
535 {
536 // anything else put it in current directory
537 dir->WriteTObject(obj);
538 }
539 if (delete_when_done) delete obj;
540 }
541 }
542
543 nlohmann::ordered_json to_JSON(TSeqCollection* tseq)
544 {
545 using json = nlohmann::ordered_json;
546 json j;
547
548 TIter nextElem(tseq);
549 TObject* obj;
550 while ((obj = nextElem()) != 0)
551 {
552 // If Results (or Config) directory contatins hist - ignore it (do not write in to the file), it
553 // should to be writen to the outer level before
554 if ((strncmp(obj->ClassName(), "TH", 2) == 0) || (strncmp(obj->ClassName(), "TGraph", 6) == 0) ||
555 (strncmp(obj->ClassName(), "TProfile", 8) == 0) || (strncmp(obj->ClassName(), "TEfficiency", 11) == 0) ||
556 (strncmp(obj->GetName(), "Reference", 9) == 0))
557
558 {
559 continue;
560 }
561 TSeqCollection* tmpList = dynamic_cast<TSeqCollection*>(obj);
562 if (tmpList != 0)
563 { // Nested object
564 // Write TSeqCollection_names as keys and content of them as a values
565 // Convert TString to string
566 std::string key_name_string(obj->GetName());
567 j.emplace(key_name_string, to_JSON(tmpList));
568 }
569 else
570 { // leaf
571 j = obj->GetName();
572 }
573 }
574 return j;
575 }
576
578 {
579 flushResults();
580 m_file->SetBit(TFile::kDevNull);
581
583 m_file.get(), dynamic_cast<TSeqCollection*>(m_outputList->First()), m_file.get(), 4, HanOutput_FileVersion);
584
585 if (HanOutput_FileVersion == 2)
586 {
587 m_file->cd("HanMetadata_");
588 TDirectory* version_dir = gDirectory->mkdir("File");
589 version_dir->cd();
590 TDirectory* version_subdir = gDirectory->mkdir("Version_name");
591 version_subdir->cd();
592 TObjString file_version;
593 file_version.Write("V.2.3");
594 }
595 m_file->Write();
596 m_file->Flush();
597 }
598
600 {
602 config->GetRegexList(m_regexlist);
603 }
604
606 {
607 m_retainUnpubData = true;
608
609 DQRegMap_t::const_iterator dqRegIter = m_dqRegs.begin();
610 DQRegMap_t::const_iterator dqRegEnd = m_dqRegs.end();
611 for (; dqRegIter != dqRegEnd; ++dqRegIter)
612 {
613 std::string regname = dqRegIter->first->getName();
614 m_unpublishedDQPars.erase(regname);
615 }
616
617 DQParSet_t::const_iterator regexItr = m_regexlist.begin();
618 DQParSet_t::const_iterator regexEnd = m_regexlist.end();
619 for (; regexItr != regexEnd; ++regexItr)
620 {
621 m_unpublishedDQPars.erase(*regexItr);
622 }
623
624 dqm_core::Result::Status status(dqm_core::Result::Undefined);
625 dqm_core::Result result(status);
626
627 DQParSet_t::const_iterator unpubIter = m_unpublishedDQPars.begin();
628 DQParSet_t::const_iterator unpubEnd = m_unpublishedDQPars.end();
629 for (; unpubIter != unpubEnd; ++unpubIter)
630 {
631 const std::string& name = *unpubIter;
632 // reduce verbosity
633 // std::cout << "--> Publishing missing object: \"" << name << "\"\n";
634 publishResult(name, result);
635 }
636
637 m_retainUnpubData = false;
638 }
639
640 // *********************************************************************
641 // Protected Methods
642 // *********************************************************************
643
645 : m_result(new TTree("result", "Assessment Result")), m_status(new char[s_charArrSize])
646 {
647 m_result->SetDirectory(dir);
648 m_result->Branch("Status", m_status, "Status/C");
649 }
650
652
653 void HanOutput::Result::fill(const dqm_core::Result& result)
654 {
655 copyString(m_status, StatusToStr(result.status_));
656 m_result->Fill();
657 }
658
659 void HanOutput::Result::write() { m_result->Write(); }
660
661 void HanOutput::Result::copyString(char* to, const std::string& from)
662 {
663 int i = 0;
664 const char* f = from.c_str();
665 while (++i < s_charArrSize && (*to++ = *f++) != 0)
666 ;
667 if (i == s_charArrSize)
668 {
669 *to = 0;
670 }
671 }
672
673 bool HanOutput::RegionNameComp::operator()(const dqm_core::Region* a, const dqm_core::Region* b) const
674 {
675 return (a->getName() < b->getName());
676 }
677
678 // *********************************************************************
679 // Private Methods
680 // *********************************************************************
681
683
684} // namespace dqi
685
686namespace
687{
688
689 std::string StatusToStr(const dqm_core::Result::Status& status)
690 {
691 switch (status)
692 {
693 case dqm_core::Result::Red:
694 return "Red";
695 case dqm_core::Result::Yellow:
696 return "Yellow";
697 case dqm_core::Result::Green:
698 return "Green";
699 case dqm_core::Result::Disabled:
700 return "Disabled";
701 case dqm_core::Result::Undefined:
702 default:
703 return "Undefined";
704 }
705 }
706
707} // namespace
const boost::regex ref(r_ef)
nlohmann::json json
static Double_t a
Header file for AthHistogramAlgorithm.
Result(Muon::CscStripStatus sstat=Muon::CscStrStatUndefined, Muon::CscTimeStatus tstat=Muon::CscTimeStatusUndefined)
virtual const char * GetValue() const
bool operator()(const dqm_core::Region *a, const dqm_core::Region *b) const
void copyString(char *to, const std::string &from)
std::unique_ptr< TTree > m_result
Definition HanOutput.h:82
static const int s_charArrSize
Definition HanOutput.h:84
virtual void publishMissingDQPars()
virtual void setConfig(HanConfig *config)
std::map< std::string, TSeqCollection * > DQOutputMap_t
Definition HanOutput.h:45
virtual void activate()
DQParSet_t m_unpublishedDQPars
Definition HanOutput.h:103
std::unique_ptr< TFile > m_file
Definition HanOutput.h:100
HanConfig * m_config
Definition HanOutput.h:111
virtual void setInput(TDirectory *input)
DQResultMap_t m_dqResults
Definition HanOutput.h:107
virtual ~HanOutput()
virtual void deactivate()
virtual void publishResult(const std::string &name, const dqm_core::Result &result)
TSeqCollection * m_outputList
Definition HanOutput.h:110
Version HanOutput_FileVersion
Definition HanOutput.h:43
virtual void flushResults()
DQParMap_t m_dqPars
Definition HanOutput.h:104
std::string m_fileName
Definition HanOutput.h:99
TDirectory * m_input
Definition HanOutput.h:113
bool m_retainUnpubData
Definition HanOutput.h:101
DQRegMap_t m_dqRegs
Definition HanOutput.h:105
DQParSet_t m_regexlist
Definition HanOutput.h:112
DQOutputMap_t * m_outputMap
Definition HanOutput.h:108
virtual void addListener(const std::string &name, dqm_core::OutputListener *listener)
int r
Definition globals.cxx:22
std::map< std::string, int > dirs
list of directories to be explicitly included, together with corresponding depths of subdirectories
Definition hcg.cxx:102
TSeqCollection * newTObjArray(const char *name, TObject *obj=0, Int_t size=TCollection::kInitCapacity)
Definition HanUtils.cxx:27
bool setNameGeneral(TObject *obj, const std::string &name)
Definition HanOutput.cxx:44
static void WriteListToDirectory(TDirectory *dir, TSeqCollection *list, TFile *file, int level, int HanOutput_FileVersion)
static bool include_hist(TObject *obj)
nlohmann::ordered_json to_JSON(TSeqCollection *tseq)
Converts sequense, containing TDirectories and strings to JSON file.
TKey * getObjKey(TDirectory *dir, const std::string &path)
Definition HanUtils.cxx:36
TFile * file