Belle II Software development
RootMergeable< T > Class Template Reference

Wrap a root histogram or TNtuple to make it mergeable. More...

#include <RootMergeable.h>

Inheritance diagram for RootMergeable< T >:
Mergeable

Public Member Functions

 RootMergeable ()
 default constructor for root.
 
template<class ... Args>
 RootMergeable (Args &&... params)
 Constructor, forwards all arguments to T constructor.
 
void assign (T *p)
 Replace wrapped object with p (takes ownership).
 
T & get ()
 Get the wrapped root object.
 
const T & get () const
 Get the wrapped root object.
 
void write (TDirectory *file)
 Write the wrapped object into 'file', overwriting existing objects of same name.
 
virtual void merge (const Mergeable *other) override
 Merge object 'other' into this one.
 
virtual void clear () override
 Clear content of this object (e.g.
 
virtual void removeSideEffects () override
 An ugly little method that is called before event() for input and worker processes.
 
virtual void RecursiveRemove (TObject *obj) override
 Called from ROOT if obj is deleted.
 
virtual Long64_t Merge (TCollection *hlist)
 Allow merging using TFileMerger if saved directly to a file.
 
virtual void Reset ()
 Root-like Reset function for "template compatibility" with ROOT objects.
 
virtual void SetDirectory (TDirectory *)
 Root-like SetDirectory function for "template compatibility" with ROOT objects.
 

Private Member Functions

 ClassDefOverride (RootMergeable, 2)
 Wrap a root histogram or ntuple to make them mergeable.
 
 ClassDef (Mergeable, 0)
 Abstract base class for objects that can be merged.
 

Private Attributes

T * m_wrapped
 Wrapped root object.
 

Detailed Description

template<class T>
class Belle2::RootMergeable< T >

Wrap a root histogram or TNtuple to make it mergeable.

To use it to save data in your module:

setPropertyFlags(c_ParallelProcessingCertified | c_TerminateInAllProcesses);

create RootMergeable<X> in initalize (or in your constructor) of durability DataStore::c_Persistent, register it by calling registerInDataStore() and construct() the actual histogram. Especially for larger TTrees, you should also create a TFile and cd() into it before creating the histogram. To actually save the objects, use the following in terminate() to ensure this is done only in the output process (where the data from all events will be collected):

//use TFile you created in initialize()
mergeablePtr->write(m_file);
}
static bool isOutputProcess()
Return true if the process is an output process.
Definition: ProcHandler.cc:232
static bool parallelProcessingUsed()
Returns true if multiple processes have been spawned, false in single-core mode.
Definition: ProcHandler.cc:226

This should work out of the box for TTree, TNtuple, TH1F, TH2F, TH1D, and TH2D. Additional template instantiations need an entry in framework/pcore/include/linkdef.h, please contact the framework librarian if your use case requires other classes.

Be aware that for larger histograms, this way of sharing the data may not be a good idea. E.g. for hundred thousand bins, basf2 would transfer about half a megabyte in each event, which may take a significant fraction of total processing time. Trees or Ntuples will however only transfer the newly added data, which is probably manageable.

To deal with ownership issues arising from objects belonging to TFiles, each RootMergeable object is added to the global list gROOT->GetListOfCleanups(), which will ensure RootMergeable::RecursiveRemove() is called when m_wrapped is deleted.

See also
Mergeable

Definition at line 61 of file RootMergeable.h.

Constructor & Destructor Documentation

◆ RootMergeable() [1/2]

RootMergeable ( )
inline

default constructor for root.

Definition at line 64 of file RootMergeable.h.

64: m_wrapped(nullptr) { }
T * m_wrapped
Wrapped root object.

◆ RootMergeable() [2/2]

RootMergeable ( Args &&...  params)
inlineexplicit

Constructor, forwards all arguments to T constructor.

Definition at line 66 of file RootMergeable.h.

66 : m_wrapped(new T(std::forward<Args>(params)...))
67 {
68 m_wrapped->SetBit(TObject::kMustCleanup); //ensure RecursiveRemove() is called
69 gROOT->GetListOfCleanups()->Add(this);
70 }

◆ ~RootMergeable()

virtual ~RootMergeable ( )
inlinevirtual

Definition at line 72 of file RootMergeable.h.

73 {
74 gROOT->GetListOfCleanups()->Remove(this);
75 delete m_wrapped;
76 }

Member Function Documentation

◆ assign()

void assign ( T *  p)
inline

Replace wrapped object with p (takes ownership).

Definition at line 79 of file RootMergeable.h.

80 {
81 delete m_wrapped;
82 m_wrapped = p;
83 m_wrapped->SetBit(TObject::kMustCleanup);
84 }

◆ clear()

virtual void clear ( )
inlineoverridevirtual

Clear content of this object (e.g.

set to zeroes).

Called after sending the objects to another process. If no clearing is performed, the same data (e.g. histogram entries) might be added again and again in each event.

Implements Mergeable.

Definition at line 130 of file RootMergeable.h.

131 {
132 m_wrapped->Reset();
133 }

◆ get() [1/2]

T & get ( )
inline

Get the wrapped root object.

Definition at line 87 of file RootMergeable.h.

87{ return *m_wrapped; }

◆ get() [2/2]

const T & get ( ) const
inline

Get the wrapped root object.

Definition at line 90 of file RootMergeable.h.

90{ return *m_wrapped; }

◆ merge()

virtual void merge ( const Mergeable other)
inlineoverridevirtual

Merge object 'other' into this one.

Your derived class should implement this function. You can static_cast 'other' to your own type (when called, this and other are guaranteed to point to objects of the same type).

Note that 'other' will be deleted after the merge, so make sure you copy all data from it that you will need.

Implements Mergeable.

Definition at line 115 of file RootMergeable.h.

116 {
117 auto* otherMergeable = const_cast<RootMergeable<T>*>(static_cast<const RootMergeable<T>*>(other));
118 TList list;
119 list.SetOwner(false);
120 list.Add(&otherMergeable->get());
121
122 m_wrapped->Merge(&list);
123 }

◆ Merge()

Long64_t Merge ( TCollection *  hlist)
virtualinherited

Allow merging using TFileMerger if saved directly to a file.

Note
dictionaries containing your Mergeable class need to be loaded, so 'hadd' will not work currently.

Definition at line 14 of file Mergeable.cc.

15{
16 Long64_t nMerged = 0;
17 if (hlist) {
18 const Mergeable* xh = nullptr;
19 TIter nxh(hlist);
20 while ((xh = dynamic_cast<Mergeable*>(nxh()))) {
21 // Add xh to me
22 merge(xh);
23 ++nMerged;
24 }
25 }
26 return nMerged;
27}
Abstract base class for objects that can be merged.
Definition: Mergeable.h:31
virtual void merge(const Mergeable *other)=0
Merge object 'other' into this one.

◆ RecursiveRemove()

virtual void RecursiveRemove ( TObject *  obj)
inlineoverridevirtual

Called from ROOT if obj is deleted.

Kill pointer to avoid double free.

Definition at line 150 of file RootMergeable.h.

151 {
152 if (obj == m_wrapped)
153 m_wrapped = nullptr;
154 }

◆ removeSideEffects()

virtual void removeSideEffects ( )
inlineoverridevirtual

An ugly little method that is called before event() for input and worker processes.

Main use case is to detach any attached TFile from this object. In the output process, it can stay attached (and grow as much as it likes).

Reimplemented from Mergeable.

Definition at line 140 of file RootMergeable.h.

141 {
142 if (!m_wrapped) return;
143
144 m_wrapped->SetDirectory(nullptr);
145 //if we are the only owner, this becomes unnecessary
146 gROOT->GetListOfCleanups()->Remove(this);
147 }

◆ Reset()

virtual void Reset ( )
inlinevirtualinherited

Root-like Reset function for "template compatibility" with ROOT objects.

Alias for clear().

Definition at line 66 of file Mergeable.h.

66{clear();}
virtual void clear()=0
Clear content of this object (e.g.

◆ SetDirectory()

virtual void SetDirectory ( TDirectory *  )
inlinevirtualinherited

Root-like SetDirectory function for "template compatibility" with ROOT objects.

Does nothing.

Definition at line 68 of file Mergeable.h.

68{}

◆ write()

void write ( TDirectory *  file)
inline

Write the wrapped object into 'file', overwriting existing objects of same name.

This function should be prefered to calling Write() by hand.

Note
wrapped object must already be in 'file' before filled, or not part of any file at all. This function will throw an error and might crash if this is not the case.

Definition at line 98 of file RootMergeable.h.

99 {
100 if (m_wrapped->GetDirectory() != nullptr and m_wrapped->GetDirectory() != file) {
101 B2ERROR("RootMergeable: wrapped object belongs to other file, Write() might crash. Make sure your histogram/ntuple already belongs to the file you want to save it to before filling (e.g. in initialize())");
102 }
103 file->cd();
104 m_wrapped->Write(nullptr, TObject::kOverwrite);
106 }
virtual void removeSideEffects() override
An ugly little method that is called before event() for input and worker processes.

Member Data Documentation

◆ m_wrapped

T* m_wrapped
private

Wrapped root object.

Definition at line 158 of file RootMergeable.h.


The documentation for this class was generated from the following file: