16#include <unordered_map>
30#ifdef HAS_RNTUPLE_SUPPORT
31#include "ROOT/RNTuple.hxx"
32#include "ROOT/RNTupleModel.hxx"
33#include "ROOT/RField.hxx"
34#include "ROOT/RNTupleWriter.hxx"
35#include "ROOT/RNTupleWriteOptions.hxx"
44#define BRANCH_VECTOR_MAX_SIZE 25000
70 m_buffer.reserve(
sizeof(
double)*count);
86 template <
typename T = u
int8_t>
91 template <
typename T = u
int8_t>
99 return *
reinterpret_cast<T*
>(
m_buffer.data() + entry.offset);
102 template <
typename T>
105 return *
reinterpret_cast<const T*
>(
m_buffer.data() + entry.offset);
112 if (entry.type !=
'D') {
113 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store double value '" + entry.name +
"'");
120 if (entry.type !=
'F') {
121 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store float value '" + entry.name +
"'");
128 if (entry.type !=
'I') {
129 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store int value '" + entry.name +
"'");
136 if (entry.type !=
'L') {
137 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store long long value '" + entry.name +
"'");
144 if (entry.type !=
'S') {
145 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store short value '" + entry.name +
"'");
153 if (entry.type !=
's') {
154 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store short value '" + entry.name +
"'");
161 if (entry.type !=
'i') {
162 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store unsigned int value '" + entry.name +
"'");
169 if (entry.type !=
'l') {
170 throw std::invalid_argument(
"Type mismatch: entry type '" + std::string(1, entry.type) +
"' cannot store long long value '" + entry.name +
"'");
179 template <
typename T>
182 throw std::out_of_range(
"QwRootTreeBranchVector::back() called on empty container");
184 const auto& last_entry =
m_entries.back();
185 return *
reinterpret_cast<T*
>(
m_buffer.data() + last_entry.offset);
188 template <
typename T>
191 throw std::out_of_range(
"QwRootTreeBranchVector::back() called on empty container");
193 const auto& last_entry =
m_entries.back();
194 return *
reinterpret_cast<const T*
>(
m_buffer.data() + last_entry.offset);
197 void push_back(
const std::string& name,
const char type =
'D') {
202 throw std::out_of_range(
"QwRootTreeBranchVector::push_back() requires buffer resize beyond reserved capacity");
208 Entry entry{name, offset, entry_size, type};
211 const std::size_t required = offset + entry_size;
212 if (required >
m_buffer.capacity()) {
213 throw std::out_of_range(
"QwRootTreeBranchVector::push_back() requires buffer resize beyond reserved capacity");
221 void push_back(
const TString& name,
const char type =
'D') {
222 push_back(std::string(name.Data()), type);
226 void push_back(
const char* name,
const char type =
'D') {
231 static const std::string separator =
":";
232 std::ostringstream stream;
239 stream << entry.name <<
"/" << entry.type;
246 std::ostringstream stream;
247 stream <<
"QwRootTreeBranchVector: " <<
m_entries.size() <<
" entries, "
249 size_t end_offset = (end_index == 0 || end_index >
m_entries.size()) ?
252 stream <<
"QwRootTreeBranchVector: buffer at 0x" << std::hex << (
void*) &
m_buffer[0] <<
'\n';
253 stream <<
"QwRootTreeBranchVector: entries at 0x" << std::hex << (
void*) &
m_entries[0] <<
'\n';
254 for (
size_t offset =
m_entries[start_index].offset; offset < end_offset; offset += 4) {
256 <<
" [" << offset <<
"] "
258 <<
" offset=0x" << offset
259 <<
" (0x" << std::setw(4) << std::setfill(
'0')
260 << offset -
m_entries[start_index].offset <<
")"
263 for (std::size_t
byte = 0;
byte < 4; ++byte) {
264 stream << std::hex << std::setw(2) << std::setfill(
'0')
265 <<
static_cast<unsigned int>(
m_buffer[offset + byte])
270 end_index = (end_index == 0 || end_index >
m_entries.size()) ?
273 for (
size_type index = start_index; index < end_index; ++index) {
276 <<
" [" << index <<
"] "
278 <<
" offset=0x" << entry.offset
279 <<
" (0x" << std::setw(4) << std::setfill(
'0')
280 << entry.offset -
m_entries[start_index].offset <<
")"
281 <<
" size=0x" << entry.size
284 for (std::size_t
byte =
GetTypeSize(entry.type);
byte > 0; --
byte) {
285 stream << std::hex << std::setw(2) << std::setfill(
'0')
286 <<
static_cast<unsigned int>((
m_buffer.data() + entry.offset)[
byte - 1]);
289 <<
" name=" << entry.name <<
"/" << entry.type
300 return sizeof(double);
302 return sizeof(float);
304 return sizeof(
long long);
306 return sizeof(
unsigned long long);
310 return sizeof(
unsigned int);
312 return sizeof(short);
314 return sizeof(
unsigned short);
316 throw std::invalid_argument(
"Unsupported branch type code: " + std::string(1, type));
321 const std::size_t alignment = 4u;
322 return (offset + (alignment - 1u)) & ~(alignment - 1u);
329 switch (entry.
type) {
351 template <
typename T>
353 std::ostringstream stream;
374 QwRootTree(
const std::string& name,
const std::string& desc,
const std::string& prefix =
"")
391 QwRootTree(
const std::string& name,
const std::string& desc, T&
object,
const std::string& prefix =
"")
433 fTree->SetDirectory(gDirectory);
441 std::string name =
"units";
447 std::string name =
"previous_entry_in_" + to->
fName;
457 TString prefix = Form(
"%s",
fPrefix.c_str());
458 object.ConstructBranchAndVector(
fTree, prefix,
fVector);
461 fType =
typeid(object).name();
465 QwError <<
"The branch vector is too large: " <<
fVector.size() <<
" leaves! "
478 if (
typeid(
object).name() ==
fType) {
480 object.FillTreeVector(
fVector);
482 QwError <<
"Attempting to fill tree vector for type " <<
fType <<
" with "
483 <<
"object of type " <<
typeid(object).name() <<
QwLog::endl;
489 return fTree->AutoSave(option);
504 Int_t retval =
fTree->Fill();
585 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,26,00)
599 if (
fTree)
fTree->SetBasketSize(
"*",basketsize);
608#ifdef HAS_RNTUPLE_SUPPORT
622 QwRootNTuple(
const std::string& name,
const std::string& desc,
const std::string& prefix =
"")
623 : fName(name), fDesc(desc), fPrefix(prefix), fType(
"type undefined"),
624 fCurrentEvent(0), fNumEventsCycle(0), fNumEventsToSave(0), fNumEventsToSkip(0) {
626 fModel = ROOT::RNTupleModel::Create();
631 QwRootNTuple(
const std::string& name,
const std::string& desc, T&
object,
const std::string& prefix =
"")
632 : fName(name), fDesc(desc), fPrefix(prefix), fType(
"type undefined"),
633 fCurrentEvent(0), fNumEventsCycle(0), fNumEventsToSave(0), fNumEventsToSkip(0) {
635 fModel = ROOT::RNTupleModel::Create();
638 ConstructFieldsAndVector(
object);
642 virtual ~QwRootNTuple() {
659 void ConstructFieldsAndVector(T&
object) {
664 TString prefix = Form(
"%s", fPrefix.c_str());
665 object.ConstructNTupleAndVector(fModel, prefix, fVector, fFieldPtrs);
668 fType =
typeid(object).name();
672 QwError <<
"The field vector is too large: " << fVector.size() <<
" fields! "
679 fVector.shrink_to_fit();
685 void InitializeWriter(TFile* file) {
692 if (fVector.empty()) {
699 ROOT::RNTupleWriteOptions options;
700 options.SetCompression(ROOT::RCompressionSetting::EAlgorithm::kLZ4, 4);
704 fWriter = ROOT::RNTupleWriter::Append(std::move(fModel), fName, *file, options);
706 QwMessage <<
"Created RNTuple '" << fName <<
"' with LZ4 compression in file " << file->GetName() <<
QwLog::endl;
708 }
catch (
const std::exception& e) {
709 QwError <<
"Failed to create RNTuple writer for '" << fName <<
"': " << e.what() <<
QwLog::endl;
715 void FillNTupleFields(
const T&
object) {
716 if (
typeid(
object).name() == fType) {
718 object.FillNTupleVector(fVector);
722 for (
size_t i = 0; i < fVector.size() && i < fFieldPtrs.size(); ++i) {
724 *(fFieldPtrs[i]) = fVector[i];
734 if (fNumEventsCycle > 0) {
735 fCurrentEvent %= fNumEventsCycle;
741 QwError <<
"Attempting to fill RNTuple vector for type " << fType <<
" with "
742 <<
"object of type " <<
typeid(object).name() <<
QwLog::endl;
754 const std::string& GetName()
const {
return fName; }
756 const std::string& GetDesc()
const {
return fDesc; }
758 const std::string& GetPrefix()
const {
return fPrefix; }
760 std::string GetType()
const {
return fType; }
763 void SetPrescaling(UInt_t num_to_save, UInt_t num_to_skip) {
764 fNumEventsToSave = num_to_save;
765 fNumEventsToSkip = num_to_skip;
766 fNumEventsCycle = fNumEventsToSave + fNumEventsToSkip;
771 QwMessage << GetName() <<
", " << GetType();
773 QwMessage <<
" (prefix " << GetPrefix() <<
")";
780 std::unique_ptr<ROOT::RNTupleModel> fModel;
781 std::unique_ptr<ROOT::RNTupleWriter> fWriter;
784 std::vector<Double_t> fVector;
785 std::vector<std::shared_ptr<Double_t>> fFieldPtrs;
788 const std::string fName;
789 const std::string fDesc;
790 const std::string fPrefix;
796 UInt_t fCurrentEvent;
797 UInt_t fNumEventsCycle;
798 UInt_t fNumEventsToSave;
799 UInt_t fNumEventsToSkip;
801 friend class QwRootFile;
863 void ConstructIndices(
const std::string& from,
const std::string& to,
bool reverse =
true);
867 void ConstructTreeBranches(
const std::string& name,
const std::string& desc, T&
object,
const std::string& prefix =
"");
875#ifdef HAS_RNTUPLE_SUPPORT
878 void ConstructNTupleFields(
const std::string& name,
const std::string& desc, T&
object,
const std::string& prefix =
"");
881 void FillNTupleFields(
const std::string& name,
const T&
object);
884 void FillNTupleFields(
const T&
object);
903 static Int_t update_count = 0;
908 std::string type =
typeid(object).name();
911 if (! hasDir)
return;
913 object.FillHistograms();
918 void NewTree(
const std::string& name,
const std::string& desc) {
930#ifdef HAS_RNTUPLE_SUPPORT
932 void NewNTuple(
const std::string& name,
const std::string& desc) {
934 QwRootNTuple *ntuple = 0;
935 if (! HasNTupleByName(name)) {
936 ntuple =
new QwRootNTuple(name, desc);
944 fNTupleByName[name].push_back(ntuple);
964 std::map< const std::string, std::vector<QwRootTree*> >::iterator iter;
966 retval += iter->second.front()->Fill();
971#ifdef HAS_RNTUPLE_SUPPORT
973 void FillNTuple(
const std::string& name) {
974 if (HasNTupleByName(name)) {
975 fNTupleByName[name].front()->Fill();
980#ifdef HAS_RNTUPLE_SUPPORT
984 std::map< const std::string, std::vector<QwRootNTuple*> >::iterator iter;
985 for (iter = fNTupleByName.begin(); iter != fNTupleByName.end(); iter++) {
986 iter->second.front()->Fill();
995 std::map< const std::string, std::vector<QwRootTree*> >::const_iterator iter;
997 QwMessage << iter->first <<
": " << iter->second.size()
1000 std::vector<QwRootTree*>::const_iterator tree;
1001 for (tree = iter->second.begin(); tree != iter->second.end(); tree++) {
1010 std::map< const std::string, TDirectory* >::const_iterator iter;
1018 template <
class T >
1019 Int_t
WriteObject(
const T* obj,
const char* name, Option_t* option =
"", Int_t bufsize = 0) {
1030 QwMessage <<
"TMapFile memory resident size: "
1032 4 /
sizeof(int32_t) / 1024 / 1024 <<
" MiB"
1039 nBytes += iter->second.front()->AutoSave(
"SaveSelf");
1042 << nBytes/1000000 <<
"MB (inaccurate number)"
1059 std::vector<TString> subdirs;
1060 TIter next(dir->GetListOfKeys());
1062 while ((key = (TKey*)next())) {
1063 if (TString(key->GetClassName()) ==
"TDirectoryFile") {
1064 subdirs.push_back(key->GetName());
1069 for (
const auto& name : subdirs) {
1070 TDirectory* sub =
dynamic_cast<TDirectory*
>(dir->Get(name));
1076 TList* list = dir->GetList();
1078 list->Clear(
"nodelete");
1088 if (!iter->second.empty() && iter->second.front()) {
1089 TTree* tree = iter->second.front()->GetTree();
1090 if (tree && tree->GetEntries() > 0) {
1098 fRootFile->Write(0, TObject::kOverwrite);
1109#ifdef HAS_RNTUPLE_SUPPORT
1110 if (!fNTupleByName.empty()) {
1116#ifdef HAS_RNTUPLE_SUPPORT
1120 for (
auto& pair : fNTupleByName) {
1121 for (
auto& ntuple : pair.second) {
1122 if (ntuple) ntuple->Close();
1136 Bool_t
cd(
const char* path = 0) {
1137 Bool_t status = kTRUE;
1144 TDirectory*
mkdir(
const char* name,
const char* title =
"") {
1151 Int_t
Write(
const char* name = 0, Int_t option = 0, Int_t bufsize = 0) {
1233 std::map< const std::type_index , std::vector<QwRootTree*> >
fTreeByType;
1236#ifdef HAS_RNTUPLE_SUPPORT
1238 std::map< const std::string, std::vector<QwRootNTuple*> > fNTupleByName;
1239 std::map< const void* , std::vector<QwRootNTuple*> > fNTupleByAddr;
1240 std::map< const std::type_index , std::vector<QwRootNTuple*> > fNTupleByType;
1243 Bool_t fEnableRNTuples;
1252 template <
class T >
1254 const std::type_index type =
typeid(object);
1259 template <
class T >
1261 const void* addr =
static_cast<const void*
>(&object);
1266#ifdef HAS_RNTUPLE_SUPPORT
1268 bool HasNTupleByName(
const std::string& name) {
1269 if (fNTupleByName.count(name) == 0)
return false;
1273 template <
class T >
1274 bool HasNTupleByType(
const T&
object) {
1275 const std::type_index type =
typeid(object);
1276 if (fNTupleByType.count(type) == 0)
return false;
1280 template <
class T >
1281 bool HasNTupleByAddr(
const T&
object) {
1282 const void* addr =
static_cast<const void*
>(&object);
1283 if (fNTupleByAddr.count(addr) == 0)
return false;
1298 template <
class T >
1300 std::string type =
typeid(object).name();
1354 const std::string& name,
1355 const std::string& desc,
1357 const std::string& prefix)
1373 tree =
new QwRootTree(name, desc,
object, prefix);
1378 else if (name ==
"mul")
1381 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,26,00)
1398 const void* addr =
static_cast<const void*
>(&object);
1399 const std::type_index type =
typeid(object);
1413 const std::string& name,
1422 const void* addr =
static_cast<const void*
>(&object);
1425 for (
size_t tree = 0; tree <
fTreeByAddr[addr].size(); tree++) {
1426 if (
fTreeByAddr[addr].at(tree)->GetName() == name) {
1427 fTreeByAddr[addr].at(tree)->FillTreeBranches(
object);
1445 const void* addr =
static_cast<const void*
>(&object);
1448 for (
size_t tree = 0; tree <
fTreeByAddr[addr].size(); tree++) {
1449 fTreeByAddr[addr].at(tree)->FillTreeBranches(
object);
1454#ifdef HAS_RNTUPLE_SUPPORT
1463void QwRootFile::ConstructNTupleFields(
1464 const std::string& name,
1465 const std::string& desc,
1467 const std::string& prefix)
1470 if (!fEnableRNTuples)
return;
1473 QwRootNTuple* ntuple = 0;
1476 if (fNTupleByName.count(name) == 0) {
1479 ntuple =
new QwRootNTuple(name, desc,
object, prefix);
1487 else if (name ==
"mul")
1498 const void* addr =
static_cast<const void*
>(&object);
1499 const std::type_index type =
typeid(object);
1500 fNTupleByName[name].push_back(ntuple);
1501 fNTupleByAddr[addr].push_back(ntuple);
1502 fNTupleByType[type].push_back(ntuple);
1512void QwRootFile::FillNTupleFields(
1513 const std::string& name,
1517 if (! HasNTupleByName(name))
return;
1519 if (! HasNTupleByType(
object))
return;
1522 const void* addr =
static_cast<const void*
>(&object);
1525 for (
size_t ntuple = 0; ntuple < fNTupleByAddr[addr].size(); ntuple++) {
1526 if (fNTupleByAddr[addr].at(ntuple)->GetName() == name) {
1527 fNTupleByAddr[addr].at(ntuple)->FillNTupleFields(
object);
1538void QwRootFile::FillNTupleFields(
1542 if (! HasNTupleByAddr(
object))
return;
1545 const void* addr =
static_cast<const void*
>(&object);
1548 for (
size_t ntuple = 0; ntuple < fNTupleByAddr[addr].size(); ntuple++) {
1549 fNTupleByAddr[addr].at(ntuple)->FillNTupleFields(
object);
1565 std::string type =
typeid(object).name();
1567 fRootFile->GetDirectory((
"/" + name).c_str()) ?
1568 fRootFile->GetDirectory((
"/" + name).c_str()) :
1569 fRootFile->GetDirectory(
"/")->mkdir(name.c_str());
1576 QwMessage <<
"QwRootFile::ConstructObjects::detectors address "
1578 <<
" and its name " << name
1581 std::string type =
typeid(object).name();
1584 object.ConstructObjects();
1602 std::string type =
typeid(object).name();
1604 fRootFile->GetDirectory((
"/" + name).c_str()) ?
1605 fRootFile->GetDirectory((
"/" + name).c_str()) :
1606 fRootFile->GetDirectory(
"/")->mkdir(name.c_str());
1614 QwMessage <<
"QwRootFile::ConstructHistograms::detectors address "
1616 <<
" and its name " << name
1619 std::string type =
typeid(object).name();
1623 object.ConstructHistograms();
1633 TList *param_list = (TList*)
fRootFile->FindObjectAny(name);
1634 if (not param_list) {
1635 retval =
fRootFile->WriteObject(
object.GetParamFileNameList(name), name);
An options class which parses command line, config file and environment.
#define QwError
Predefined log drain for errors.
#define QwMessage
Predefined log drain for regular messages.
#define BRANCH_VECTOR_MAX_SIZE
unsigned long long ULong64_t
static std::ostream & endl(std::ostream &)
End of the line.
Command-line and configuration file options processor.
A helper class to manage a vector of branch entries for ROOT trees.
const void * data() const noexcept
void SetValue(size_type index, Long64_t val)
void push_back(const char *name, const char type='D')
void reserve(size_type count)
size_type size() const noexcept
void SetValue(size_type index, Int_t val)
T & value(size_type index)
static std::string FormatNumeric(T input)
std::vector< Entry > m_entries
std::string LeafList(size_type start_index=0) const
QwRootTreeBranchVector()=default
T & operator[](size_type index)
void SetValue(size_type index, Short_t val)
std::string FormatValue(const Entry &entry, size_type index) const
bool empty() const noexcept
void SetValue(size_type index, ULong64_t val)
void SetValue(size_type index, UInt_t val)
size_type data_size() const noexcept
std::vector< std::uint8_t > m_buffer
const T & operator[](size_type index) const
static std::size_t GetTypeSize(char type)
void push_back(const std::string &name, const char type='D')
std::string Dump(size_type start_index=0, size_type end_index=0) const
static std::size_t AlignOffset(std::size_t offset)
void SetValue(size_type index, Float_t val)
void SetValue(size_type index, UShort_t val)
void SetValue(size_type index, Double_t val)
const T & value(size_type index) const
void push_back(const TString &name, const char type='D')
Wrapper class for ROOT tree management with vector-based data storage.
QwRootTree(const std::string &name, const std::string &desc, T &object, const std::string &prefix="")
Constructor with name, description, and object.
Long64_t AutoSave(Option_t *option)
Int_t Fill()
Fill the tree.
void ConstructNewTree()
Construct the tree.
UInt_t fCurrentEvent
Tree prescaling parameters.
virtual ~QwRootTree()
Destructor.
const std::string fPrefix
void SetAutoFlush(Long64_t autoflush=30000000)
Set autoflush size.
void Print() const
Print the tree name and description.
Long64_t fMaxTreeSize
Maximum tree size, autoflush and autosave.
const std::string fName
Name, description.
std::string fType
Object type.
static const TString kUnitsName
void ConstructUnitsBranch()
void SetCircular(Long64_t buff=100000)
void SetMaxTreeSize(Long64_t maxsize=1900000000)
Set maximum tree size.
QwRootTree(const std::string &name, const std::string &desc, const std::string &prefix="")
Constructor with name, and description.
void SetAutoSave(Long64_t autosave=300000000)
Set autosave size.
const std::string & GetPrefix() const
Get the description of the tree.
QwRootTreeBranchVector fVector
Vector of leaves.
void ConstructBranchAndVector(T &object)
Construct the branches and vector for generic objects.
static Double_t kUnitsValue[]
TTree * GetTree() const
Get the tree pointer for low level operations.
void ConstructIndexTo(QwRootTree *to)
Construct index from this tree to another tree.
const std::string & GetDesc() const
Get the description of the tree.
TTree * fTree
Tree pointer.
void SetBasketSize(Int_t basketsize=16000)
Set basket size.
void FillTreeBranches(const T &object)
Fill the branches for generic objects.
QwRootTree(const QwRootTree *tree, T &object, const std::string &prefix="")
Constructor with existing tree, and object.
QwRootTree(const QwRootTree *tree, const std::string &prefix="")
Constructor with existing tree.
const std::string & GetName() const
Get the name of the tree.
void SetPrescaling(UInt_t num_to_save, UInt_t num_to_skip)
Set tree prescaling parameters.
std::string GetType() const
Get the object type.
Bool_t IsRootFile() const
Is the ROOT file active?
bool HasTreeByType(const T &object)
Is a tree registered for this type.
std::vector< TPRegexp > fDisabledTrees
List of excluded trees.
std::map< const std::string, std::vector< std::string > > fDirsByType
void NewTree(const std::string &name, const std::string &desc)
Create a new tree with name and description.
TString fRootFileStem
ROOT file stem.
Int_t FillTree(const std::string &name)
Fill the tree with name.
TFile * fRootFile
ROOT file.
Bool_t IsMapFile() const
Is the map file active?
bool HasDirByType(const T &object)
Is a directory registered for this type.
virtual ~QwRootFile()
Destructor.
TString fRootFileDir
ROOT files dir.
void DisableTree(const TString ®exp)
Add regexp to list of disabled trees names.
Int_t fCompressionAlgorithm
Bool_t cd(const char *path=0)
Bool_t HasAnyFilled(void)
Search for non-empty trees or histograms in the file.
Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
void PrintDirs() const
Print registered histogram directories.
static std::string fDefaultRootFileDir
Default ROOT files dir.
void PrintTrees() const
Print registered trees.
static const Int_t kMaxMapFileSize
Int_t WriteObject(const T *obj, const char *name, Option_t *option="", Int_t bufsize=0)
Write any object to the ROOT file (only valid for TFile)
std::map< const std::string, TDirectory * > fDirsByName
Directories.
void ProcessOptions(QwOptions &options)
Process the configuration options.
QwRootFile(const TString &run_label)
Constructor with run label.
UInt_t fNumHelEventsToSkip
bool IsHistoDisabled(const std::string &name)
Does this histogram directory match a disabled histogram directory?
std::map< const std::string, std::vector< QwRootTree * > > fTreeByName
Tree names, addresses, and types.
TDirectory * mkdir(const char *name, const char *title="")
void DisableHisto(const TString ®exp)
Add regexp to list of disabled histogram directories.
static void SetDefaultRootFileStem(const std::string &stem)
Set default ROOT file stem.
static void SetDefaultRootFileDir(const std::string &dir)
Set default ROOT files dir.
void ConstructTreeBranches(const std::string &name, const std::string &desc, T &object, const std::string &prefix="")
Construct the tree branches of a generic object.
UInt_t fNumMpsEventsToSave
static std::string fDefaultRootFileStem
Default ROOT file stem.
void FillHistograms(T &object)
Fill histograms of the subsystem array.
bool IsTreeDisabled(const std::string &name)
Does this tree name match a disabled tree name?
Int_t FillTrees()
Fill all registered trees.
std::map< const std::type_index, std::vector< QwRootTree * > > fTreeByType
static void DefineOptions(QwOptions &options)
Define the configuration options.
UInt_t fNumHelEventsToSave
TTree * GetTree(const std::string &name)
Get the tree with name.
bool HasTreeByAddr(const T &object)
Is a tree registered for this object.
TMapFile * fMapFile
Map file.
bool HasDirByName(const std::string &name)
Is a tree registered for this name.
void FillTreeBranches(const std::string &name, const T &object)
Fill the tree branches of a generic object by tree name.
Int_t WriteParamFileList(const TString &name, T &object)
QwRootFile()
Private default constructor.
void ConstructHistograms(const std::string &name, T &object)
Construct the histograms of a generic object.
void ClearInMemoryObjects(TDirectory *dir)
UInt_t fCircularBufferSize
std::map< const void *, std::vector< QwRootTree * > > fTreeByAddr
void ConstructObjects(const std::string &name, T &object)
Construct the histograms of a generic object.
static const Long64_t kMaxTreeSize
Maximum tree size.
std::vector< TPRegexp > fDisabledHistos
UInt_t fNumMpsEventsToSkip
Prescaling of events written to tree.
void ConstructIndices(const std::string &from, const std::string &to, bool reverse=true)
Construct indices from one tree to another tree.
bool HasTreeByName(const std::string &name)
Is a tree registered for this name.