ATLAS Offline Software
Loading...
Searching...
No Matches
HanOutput.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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 if (auto seqcoll = dynamic_cast<TSeqCollection*>((*m_outputMap)[parentName])) {
290 seqcoll->Add(resultList);
291 }
292 else {
293 std::cerr << "dynamic_cast to TSeqCollection* fails\n";
294 }
295 TKey* key = getObjKey(m_input, storename);
296 if (key != 0)
297 {
298 const char* className = key->GetClassName();
299 if ((strncmp(className, "TH", 2) == 0) || (strncmp(className, "TGraph", 6) == 0) ||
300 (strncmp(className, "TProfile", 8) == 0) || (strncmp(className, "TEfficiency", 11) == 0))
301 {
302 TNamed* transobj = dynamic_cast<TNamed*>(key->ReadObj());
303 if (transobj != NULL)
304 {
305 HanHistogramLink* hhl = new HanHistogramLink(m_input, storename);
306 if (use_full_name)
307 {
308 hhl->SetName((boost::algorithm::replace_all_copy(storename, "/", "_") + extra).c_str());
309 }
310 else
311 {
312 hhl->SetName((std::string(transobj->GetName()) + extra).c_str());
313 }
314 // transobj->SetName((std::string(transobj->GetName()) + extra).c_str());
315 // resultList->Add(transobj);
316 resultList->Add(hhl);
317 }
318 else
319 {
320 std::cerr << "TNamed* cast failed for " << storename << std::endl;
321 }
322 }
323 }
324 else
325 {
326 std::cout << "key is NULL" << std::endl;
327 }
328 }
329 else
330 {
331 std::cerr << "WARNING: Unable to find mapping for " << name << std::endl;
332 continue;
333 }
334 }
335
336
337 if (resultList)//ensure resultList is not null before dereference
338 {
339 resultList = dynamic_cast<TSeqCollection*>(resultList->FindObject("Results"));
340 }
341 //check dynamic cast
342 if (resultList == nullptr)
343 {
344 std::cerr << "Warning: no result list found associated with '" << name << "'\n";
345 continue;
346 }
347
348
349 resultList->Add(newTObjArray("Status", new TObjString(StatusToStr(result.status_).c_str()), 1));
350
351 // iterate through the tags
352 std::map<std::string, double>::const_iterator iter = result.tags_.begin();
353 for (; iter != result.tags_.end(); ++iter)
354 {
355 std::ostringstream tagval;
356 tagval << std::setprecision(4) << iter->second;
357 resultList->Add(newTObjArray(iter->first.c_str(), new TObjString(tagval.str().c_str()), 1));
358 }
359
360 // if there's an output object from the algorithm, include a clone
361 TObject* resultobj = result.getObject();
362 if (resultobj != 0)
363 {
364 TObject* resultobjclone = resultobj->Clone();
365 if (setNameGeneral(resultobj, "ResultObject"))
366 {
367 resultList->Add(resultobjclone);
368 }
369 else
370 {
371 std::cerr << "Discarding result object " << result.getObject()->GetName() << std::endl;
372 delete resultobjclone;
373 }
374 }
375
376 if (m_config != 0)
377 {
378 TObject* ref = m_config->GetReference(parentName, parname);
379 if (ref)
380 {
381 if (setNameGeneral(ref, "Reference"))
382 {
383 resultList->Add(ref);
384 }
385 else
386 {
387 std::cerr << "Discarding reference object " << ref->GetName() << std::endl;
388 }
389 }
390 }
391 }
392 }
393
394 void HanOutput::activate() { gROOT->cd(); }
395
396 void HanOutput::setInput(TDirectory* input) { m_input = input; }
397
398 static bool include_hist(TObject* obj) { //Check if object a hist or include hist
399 bool result = false;
400
401 if ((strncmp(obj->ClassName(), "TH", 2) == 0) || (strncmp(obj->ClassName(), "TGraph", 6) == 0) ||
402 (strncmp(obj->ClassName(), "TProfile", 8) == 0) || (strncmp(obj->ClassName(), "TEfficiency", 11) == 0))
403 {
404 return true;
405 }
406
407 TSeqCollection* tmpList{};
408 tmpList = dynamic_cast<TSeqCollection*>(obj);
409 if (tmpList != 0)
410 { //If it is collection - check, that it contains histograms or not
411 TIter nextElem(tmpList);
412 TObject* tmpobj{};
413 while ((tmpobj = nextElem()) != 0)
414 {
415 result = include_hist(tmpobj);
416 if (result == true)
417 {
418 return result;
419 }
420 }
421 }
422 return result;
423 }
424
426 TDirectory* dir, TSeqCollection* list, TFile* file, int level, int HanOutput_FileVersion)
427 {
428 TIter nextElem(list);
429 TObject* obj{};
430 TSeqCollection* tmpList{};
431
432 while ((obj = nextElem()) != 0)
433 {
434 bool delete_when_done = false;
435 HanHistogramLink* hhl = dynamic_cast<HanHistogramLink*>(obj);
436 if (hhl != 0)
437 {
438 obj = hhl->getObject();
439 if (!obj) continue;
440 delete_when_done = true;
441 if (not setNameGeneral(obj, hhl->GetName()))
442 {
443 std::cerr << "HanOutput.cxx, WriteListToDirectory : setNameGeneral failed\n";
444 delete obj;
445 continue;
446 };
447 }
448 if (strncmp(obj->GetName(), "Reference", 9) == 0 || strncmp(obj->GetName(), "ResultObject", 12) == 0)
449 {
450 dir->WriteTObject(obj);
451 if (delete_when_done) delete obj;
452 continue;
453 }
454 tmpList = dynamic_cast<TSeqCollection*>(obj);
455 if (tmpList != 0)
456 {
457 // Find last directory name
458 std::vector<std::string> dirs;
459 std::string str;
460 boost::split(dirs, tmpList->GetName(), boost::is_any_of("/"));
461 if (!dirs.empty())
462 {
463 if (dirs.back().empty()) dirs.pop_back(); // empty item if trailing "/"
464 str = dirs.back();
465 }
466
467 if (HanOutput_FileVersion == 2)
468 {
469 TString listname = tmpList->GetName();
470 if (listname == "Config" || listname == "Results")
471 {
473 //If yes - we should save them in the upper level
474 TIter nextElemConfRes(tmpList);
475 TObject* objInResultConfig;
476 while ((objInResultConfig = nextElemConfRes()) != 0)
477 {
478 if (include_hist(objInResultConfig))
479 {
480 //If the element consist of histograms
481 TSeqCollection* tmpList_ResConf{}; //it should be a collection type
482 tmpList_ResConf = dynamic_cast<TSeqCollection*>(objInResultConfig);
483 if ((tmpList_ResConf != 0) && (strncmp(tmpList_ResConf->GetName(), "TObjArray", 9) == 0))
484 { //Here is the special case. In case the object is an Array with the name "TObjArray", containing histograms,
485 //we should not only store it on the upper level, but also extract all the hists from it.
486 TIter nextEleminTObjArray(tmpList_ResConf);
487 TObject* objInTObjArray;
488 while ((objInTObjArray = nextEleminTObjArray()) != 0){
489 dir->WriteTObject(objInTObjArray);
490 }
491 tmpList->Remove(objInResultConfig); //This Array should not participate in JSON formation
492 }
493 else //If the element is histogram (or other Array, containing hist)- just store this obj in a higher level
494 {
495 dir->WriteTObject(objInResultConfig);
496 }
497 }
498 }
499 // For the rest of the content - Convert them to JSON
500 nlohmann::ordered_json j = to_JSON(tmpList);
501 // Then, save JSON to file as TObjString
502 // Convert json to string
503 std::string string = j.dump(4);
504 // Convert string to char *
505 char* cstr = new char[string.length() + 1];
506 std::strcpy(cstr, string.c_str());
507 // Write JSON to TObjString
508 TObjString string_to_tfile;
509 string_to_tfile.SetString(cstr);
510 dir->cd();
511 string_to_tfile.Write(listname);
512 delete[] cstr;
513 continue;
514 }
515 }
516
517 TDirectory* daughter;
518 if (!dir->FindKey(str.c_str()))
519 {
520 daughter = dir->mkdir(str.c_str());
521 }
522 else
523 {
524 std::cout << "Failed to make " << str << " from " << tmpList->GetName() << std::endl;
525 continue;
526 }
527 WriteListToDirectory(daughter, tmpList, file, level - 1, HanOutput_FileVersion);
528 if (level > 0)
529 {
530 file->Write();
531 delete daughter;
532 }
533 }
534 else if ((strncmp(obj->ClassName(), "TH", 2) == 0) || (strncmp(obj->ClassName(), "TGraph", 6) == 0) ||
535 (strncmp(obj->ClassName(), "TProfile", 8) == 0) || (strncmp(obj->ClassName(), "TEfficiency", 11) == 0))
536 {
537 dir->GetMotherDir()->WriteTObject(obj);
538 }
539 else
540 {
541 // anything else put it in current directory
542 dir->WriteTObject(obj);
543 }
544 if (delete_when_done) delete obj;
545 }
546 }
547
548 nlohmann::ordered_json to_JSON(TSeqCollection* tseq)
549 {
550 using json = nlohmann::ordered_json;
551 json j;
552
553 TIter nextElem(tseq);
554 TObject* obj;
555 while ((obj = nextElem()) != 0)
556 {
557 // If Results (or Config) directory contatins hist - ignore it (do not write in to the file), it
558 // should to be writen to the outer level before
559 if ((strncmp(obj->ClassName(), "TH", 2) == 0) || (strncmp(obj->ClassName(), "TGraph", 6) == 0) ||
560 (strncmp(obj->ClassName(), "TProfile", 8) == 0) || (strncmp(obj->ClassName(), "TEfficiency", 11) == 0) ||
561 (strncmp(obj->GetName(), "Reference", 9) == 0))
562
563 {
564 continue;
565 }
566 TSeqCollection* tmpList = dynamic_cast<TSeqCollection*>(obj);
567 if (tmpList != 0)
568 { // Nested object
569 // Write TSeqCollection_names as keys and content of them as a values
570 // Convert TString to string
571 std::string key_name_string(obj->GetName());
572 j.emplace(key_name_string, to_JSON(tmpList));
573 }
574 else
575 { // leaf
576 j = obj->GetName();
577 }
578 }
579 return j;
580 }
581
583 {
584 flushResults();
585 m_file->SetBit(TFile::kDevNull);
586
588 m_file.get(), dynamic_cast<TSeqCollection*>(m_outputList->First()), m_file.get(), 4, HanOutput_FileVersion);
589
590 if (HanOutput_FileVersion == 2)
591 {
592 m_file->cd("HanMetadata_");
593 TDirectory* version_dir = gDirectory->mkdir("File");
594 version_dir->cd();
595 TDirectory* version_subdir = gDirectory->mkdir("Version_name");
596 version_subdir->cd();
597 TObjString file_version;
598 file_version.Write("V.2.3");
599 }
600 m_file->Write();
601 m_file->Flush();
602 }
603
605 {
607 config->GetRegexList(m_regexlist);
608 }
609
611 {
612 m_retainUnpubData = true;
613
614 DQRegMap_t::const_iterator dqRegIter = m_dqRegs.begin();
615 DQRegMap_t::const_iterator dqRegEnd = m_dqRegs.end();
616 for (; dqRegIter != dqRegEnd; ++dqRegIter)
617 {
618 std::string regname = dqRegIter->first->getName();
619 m_unpublishedDQPars.erase(regname);
620 }
621
622 DQParSet_t::const_iterator regexItr = m_regexlist.begin();
623 DQParSet_t::const_iterator regexEnd = m_regexlist.end();
624 for (; regexItr != regexEnd; ++regexItr)
625 {
626 m_unpublishedDQPars.erase(*regexItr);
627 }
628
629 dqm_core::Result::Status status(dqm_core::Result::Undefined);
630 dqm_core::Result result(status);
631
632 DQParSet_t::const_iterator unpubIter = m_unpublishedDQPars.begin();
633 DQParSet_t::const_iterator unpubEnd = m_unpublishedDQPars.end();
634 for (; unpubIter != unpubEnd; ++unpubIter)
635 {
636 const std::string& name = *unpubIter;
637 // reduce verbosity
638 // std::cout << "--> Publishing missing object: \"" << name << "\"\n";
639 publishResult(name, result);
640 }
641
642 m_retainUnpubData = false;
643 }
644
645 // *********************************************************************
646 // Protected Methods
647 // *********************************************************************
648
650 : m_result(new TTree("result", "Assessment Result")), m_status(new char[s_charArrSize])
651 {
652 m_result->SetDirectory(dir);
653 m_result->Branch("Status", m_status, "Status/C");
654 }
655
657
658 void HanOutput::Result::fill(const dqm_core::Result& result)
659 {
660 copyString(m_status, StatusToStr(result.status_));
661 m_result->Fill();
662 }
663
664 void HanOutput::Result::write() { m_result->Write(); }
665
666 void HanOutput::Result::copyString(char* to, const std::string& from)
667 {
668 int i = 0;
669 const char* f = from.c_str();
670 while (++i < s_charArrSize && (*to++ = *f++) != 0)
671 ;
672 if (i == s_charArrSize)
673 {
674 *to = 0;
675 }
676 }
677
678 bool HanOutput::RegionNameComp::operator()(const dqm_core::Region* a, const dqm_core::Region* b) const
679 {
680 return (a->getName() < b->getName());
681 }
682
683 // *********************************************************************
684 // Private Methods
685 // *********************************************************************
686
688
689} // namespace dqi
690
691namespace
692{
693
694 std::string StatusToStr(const dqm_core::Result::Status& status)
695 {
696 switch (status)
697 {
698 case dqm_core::Result::Red:
699 return "Red";
700 case dqm_core::Result::Yellow:
701 return "Yellow";
702 case dqm_core::Result::Green:
703 return "Green";
704 case dqm_core::Result::Disabled:
705 return "Disabled";
706 case dqm_core::Result::Undefined:
707 default:
708 return "Undefined";
709 }
710 }
711
712} // 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