The Gaudi Framework  v39r0 (5b8b5eda)
THistWrite.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // Include files
12 #include "THistWrite.h"
13 
14 #include <GaudiKernel/ITHistSvc.h>
16 #include <GaudiKernel/MsgStream.h>
18 #include <math.h>
19 
20 #include <TDirectory.h>
21 #include <TError.h>
22 #include <TH1F.h>
23 #include <TH2F.h>
24 #include <TH3F.h>
25 #include <TKey.h>
26 #include <TProfile.h>
27 #include <TTree.h>
28 
30 
31 //------------------------------------------------------------------------------
32 THistWrite::THistWrite( const std::string& name, ISvcLocator* pSvcLocator )
33  : Algorithm( name, pSvcLocator )
34  , m_ths( nullptr )
35 //------------------------------------------------------------------------------
36 {}
37 
38 //------------------------------------------------------------------------------
40 //------------------------------------------------------------------------------
41 {
42 
43  // FIXME - Code here generates a lot of memory leak errors with the leak sanitizers, e.g.
44  //
45  // clang-format off
46  // Indirect leak of 816 byte(s) in 1 object(s) allocated from:
47  // #0 0x7f817fd0aec8 in operator new[](unsigned long) /afs/cern.ch/cms/CAF/CMSCOMM/COMM_ECAL/dkonst/GCC/build/contrib/gcc-8.2.0/src/gcc/8.2.0/libsanitizer/lsan/lsan_interceptors.cc:231
48  // #1 0x7f817bedf4b6 in TArrayD::Set(int) /mnt/build/jenkins/workspace/lcg_release_tar/BUILDTYPE/Debug/COMPILER/gcc8binutils/LABEL/centos7/build/projects/ROOT-6.18.00/src/ROOT/6.18.00/core/cont/src/TArrayD.cxx:112
49  // #2 0x7f81796c52bf in TH1D::TH1D(char const*, char const*, int, double, double) /mnt/build/jenkins/workspace/lcg_release_tar/BUILDTYPE/Debug/COMPILER/gcc8binutils/LABEL/centos7/build/projects/ROOT-6.18.00/src/ROOT/6.18.00/hist/hist/src/TH1.cxx:9627
50  // #3 0x7f817782ab5d in THistWrite::initialize() ../GaudiTestSuite/src/THist/THistWrite.cpp:94
51  // clang-format on
52  //
53  // These leaks are currently suppressed in Gaudi/job/Gaudi-LSan.supp - remove entry there to reactivate
54 
55  if ( service( "THistSvc", m_ths ).isFailure() ) {
56  error() << "Couldn't get THistSvc" << endmsg;
57  return StatusCode::FAILURE;
58  }
59 
60  // Temporary Trees
61  std::unique_ptr<TH1F> h1 = std::make_unique<TH1F>( "TempHist1", "Temporary Tree 1", 100, 0., 100. );
62  if ( m_ths->regHist( "TempHist1", std::move( h1 ) ).isFailure() ) {
63  error() << "Couldn't register TempHist1" << endmsg;
64  }
65 
66  std::unique_ptr<TH1F> h1a = std::make_unique<TH1F>( "TempHist1a", "Temporary Tree 1a", 100, 0., 100. );
67  if ( m_ths->regHist( "other/TempHist1a", std::move( h1a ) ).isFailure() ) {
68  error() << "Couldn't register TempHist1a" << endmsg;
69  }
70 
71  // Write to stream "new"
72  std::unique_ptr<TH1F> h2 = std::make_unique<TH1F>( "Tree2", "Tree 2", 100, 0., 100. );
73  if ( m_ths->regHist( "/new/Tree2", std::move( h2 ) ).isFailure() ) { error() << "Couldn't register Tree2" << endmsg; }
74 
75  // Update to stream "upd", dir "/xxx"
76  std::unique_ptr<TH1F> h3 = std::make_unique<TH1F>( "1Dgauss", "1D Gaussian", 100, -50., 50. );
77  if ( m_ths->regHist( "/upd/xxx/gauss1d", std::move( h3 ) ).isFailure() ) {
78  error() << "Couldn't register gauss1d" << endmsg;
79  }
80 
81  // Recreate 2D tree in "/"
82  std::unique_ptr<TH2F> h3a = std::make_unique<TH2F>( "2Dgauss", "2D Gaussian", 100, -50., 50., 100, -50, 50 );
83  if ( m_ths->regHist( "/rec/gauss2d", std::move( h3a ) ).isFailure() ) {
84  error() << "Couldn't register gauss2d" << endmsg;
85  }
86 
87  // 3D tree in "/"
89  std::make_unique<TH3F>( "3Dgauss", "3D Gaussian", 100, -50., 50., 100, -50, 50, 100, -50, 50 );
90  if ( m_ths->regHist( "/rec/gauss3d", std::move( h4 ) ).isFailure() ) {
91  error() << "Couldn't register gauss3d" << endmsg;
92  }
93 
94  TH1F* h5 = new TH1F( "TempHist5", "Temporary Tree 5", 100, 0., 100. );
95  if ( m_ths->regHist( "TempHist5", std::unique_ptr<TH1F>( h5 ) ).isFailure() ) {
96  error() << "Couldn't register TempHist5" << endmsg;
97  }
98  if ( strcmp( h5->GetName(), "TempHist5" ) ) {
99  error() << "Couldn't use TempHist5 afterwards. getName = " << h5->GetName() << endmsg;
100  }
101 
102  TH1D* h7 = new TH1D( "TempHist7", "Temporary Tree 7", 100, 0., 100. );
103  if ( m_ths->regHist( "TempHist7", h7 ).isFailure() ) { error() << "Couldn't register TempHist7" << endmsg; }
104  if ( strcmp( h7->GetName(), "TempHist7" ) ) {
105  error() << "Couldn't use TempHist7 afterwards. getName = " << h7->GetName() << endmsg;
106  }
107 
108  // Profile in "/"
109  std::unique_ptr<TH1> tp = std::make_unique<TProfile>( "profile", "profile", 100, -50., -50. );
110  if ( m_ths->regHist( "/rec/prof", std::move( tp ) ).isFailure() ) { error() << "Couldn't register prof" << endmsg; }
111 
112  // Tree with branches in "/trees/stuff"
113  std::unique_ptr<TTree> tr = std::make_unique<TTree>( "treename", "tree title" );
114  if ( m_ths->regTree( "/rec/trees/stuff/tree1", std::move( tr ) ).isFailure() ) {
115  error() << "Couldn't register tr" << endmsg;
116  }
117 
118  // Update to stream "upd", dir "/xxx"
119  std::unique_ptr<TH1F> h3s = std::make_unique<TH1F>( "1Dgauss_shared", "1D Gaussian", 100, -50., 50. );
120  LockedHandle<TH1> lh1( nullptr, nullptr );
121  if ( m_ths->regShared( "/upd/xxx/gauss1d_shared", std::move( h3s ), lh1 ).isFailure() ) {
122  error() << "Couldn't register gauss1d_shared" << endmsg;
123  }
124 
125  // Recreate 2D tree in "/"
126  std::unique_ptr<TH2F> h3sa = std::make_unique<TH2F>( "2Dgauss_shared", "2D Gaussian", 100, -50., 50., 100, -50, 50 );
127  LockedHandle<TH2> lh2( nullptr, nullptr );
128  if ( m_ths->regShared( "/rec/gauss2d_shared", std::move( h3sa ), lh2 ).isFailure() ) {
129  error() << "Couldn't register gauss2d_shared" << endmsg;
130  }
131 
132  // 3D tree in "/"
134  std::make_unique<TH3F>( "3Dgauss_shared", "3D Gaussian", 100, -50., 50., 100, -50, 50, 100, -50, 50 );
135  LockedHandle<TH3> lh3( nullptr, nullptr );
136  if ( m_ths->regShared( "/rec/gauss3d_shared", std::move( h4s ), lh3 ).isFailure() ) {
137  error() << "Couldn't register gauss3d_shared" << endmsg;
138  }
139 
140  return StatusCode::SUCCESS;
141 }
142 
143 //------------------------------------------------------------------------------
145 //------------------------------------------------------------------------------
146 {
147  Rndm::Numbers gauss( randSvc(), Rndm::Gauss( 0., 15. ) );
148 
149  static int n = 0;
150 
151  double x = sin( double( n ) ) * 52. + 50.;
152 
153  TH1* h( nullptr );
154  if ( m_ths->getHist( "TempHist1", h ).isSuccess() ) {
155  h->Fill( x );
156  } else {
157  error() << "Couldn't retrieve TempHist 1" << endmsg;
158  }
159 
160  if ( m_ths->getHist( "other/TempHist1a", h ).isSuccess() ) {
161  h->Fill( x );
162  } else {
163  error() << "Couldn't retrieve TempHist 1a" << endmsg;
164  }
165 
166  if ( m_ths->getHist( "/new/Tree2", h ).isSuccess() ) {
167  h->Fill( x );
168  } else {
169  error() << "Couldn't retrieve Tree2" << endmsg;
170  }
171 
172  if ( m_ths->getHist( "/upd/xxx/gauss1d", h ).isSuccess() ) {
173  for ( int i = 0; i < 1000; ++i ) { h->Fill( gauss(), 1. ); }
174  } else {
175  error() << "Couldn't retrieve 1Dgauss" << endmsg;
176  }
177 
178  TH2* h2( nullptr );
179  if ( m_ths->getHist( "/rec/gauss2d", h2 ).isSuccess() ) {
180  for ( int i = 0; i < 1000; ++i ) { h2->Fill( gauss(), gauss(), 1. ); }
181  } else {
182  error() << "Couldn't retrieve 2Dgauss" << endmsg;
183  }
184 
185  TH3* h3( nullptr );
186  if ( m_ths->getHist( "/rec/gauss3d", h3 ).isSuccess() ) {
187  for ( int i = 0; i < 1000; ++i ) { h3->Fill( gauss(), gauss(), gauss(), 1. ); }
188  } else {
189  error() << "Couldn't retrieve 3Dgauss" << endmsg;
190  }
191 
192  if ( m_ths->getHist( "TempHist5", h ).isSuccess() ) {
193  h->Fill( x );
194  } else {
195  error() << "Couldn't retrieve TempHist 5" << endmsg;
196  }
197 
198  LockedHandle<TH1> lh1( nullptr, nullptr );
199  if ( m_ths->getShared( "/upd/xxx/gauss1d_shared", lh1 ).isSuccess() ) {
200  for ( int i = 0; i < 1000; ++i ) { lh1->Fill( gauss(), 1. ); }
201  } else {
202  error() << "Couldn't retrieve 1Dgauss_shared" << endmsg;
203  }
204 
205  LockedHandle<TH2> lh2( nullptr, nullptr );
206  if ( m_ths->getShared( "/rec/gauss2d_shared", lh2 ).isSuccess() ) {
207  for ( int i = 0; i < 1000; ++i ) { lh2->Fill( gauss(), gauss(), 1. ); }
208  } else {
209  error() << "Couldn't retrieve 2Dgauss_shared" << endmsg;
210  }
211 
212  LockedHandle<TH3> lh3( nullptr, nullptr );
213  if ( m_ths->getShared( "/rec/gauss3d_shared", lh3 ).isSuccess() ) {
214  for ( int i = 0; i < 1000; ++i ) { lh3->Fill( gauss(), gauss(), gauss(), 1. ); }
215  } else {
216  error() << "Couldn't retrieve 3Dgauss_shared" << endmsg;
217  }
218 
219  TTree* tr( nullptr );
220  if ( m_ths->getTree( "/rec/trees/stuff/tree1", tr ).isFailure() ) {
221  error() << "Couldn't retrieve tree tree1" << endmsg;
222  } else {
223  if ( n == 0 ) {
224  int p1, p2, p3;
225  tr->Branch( "branch1", &p1, "point1/I" );
226  tr->Branch( "branch2", &p2, "point2/I" );
227  tr->Branch( "branch3", &p3, "point3/I" );
228 
229  for ( int i = 0; i < 1000; i++ ) {
230  p1 = i;
231  p2 = i % 10;
232  p3 = i % 7;
233 
234  tr->Fill();
235  }
236  }
237  }
238 
239  n++;
240  return StatusCode::SUCCESS;
241 }
242 
243 //------------------------------------------------------------------------------
244 void THistWrite::listKeys( TDirectory* td ) {
245  //------------------------------------------------------------------------------
246 
247  info() << "printing keys for: " << td->GetPath() << " (" << td->GetList()->GetSize() << ")" << endmsg;
248  TIter nextkey( td->GetList() );
249  while ( TKey* key = (TKey*)nextkey() ) {
250  if ( key != 0 ) {
251  info() << key->GetName() << " (" << key->IsA()->GetName()
252  << ") "
253  // << key->GetObjectStat()
254  // << " " << key->IsOnHeap()
255  << key->GetCycle() << endmsg;
256  } else {
257  info() << "key == 0" << endmsg;
258  }
259  }
260 
261  return;
262 }
263 
264 //------------------------------------------------------------------------------
266 //------------------------------------------------------------------------------
267 {
268  info() << "Finalizing..." << endmsg;
269 
270  TH1* h7 = nullptr;
271  if ( m_ths->getHist( "TempHist7", h7 ).isFailure() ) { error() << "Couldn't retrieve TempHist7" << endmsg; }
272  if ( m_ths->deReg( h7 ).isFailure() ) { error() << "Failed to deregister histogram TempHist7" << endmsg; }
273 
274  return StatusCode::SUCCESS;
275 }
ITHistSvc::deReg
virtual StatusCode deReg(const std::string &name)=0
Deregister object with given name and give up ownership (without deletion!)
THistWrite::execute
StatusCode execute() override
Definition: THistWrite.cpp:144
RndmGenerators.h
Gaudi::Algorithm::randSvc
SmartIF< IRndmGenSvc > & randSvc() const
The standard RandomGen service, Return a pointer to the service if present.
Definition: Algorithm.cpp:565
THistWrite::finalize
StatusCode finalize() override
Definition: THistWrite.cpp:265
std::move
T move(T... args)
AlgSequencer.p2
p2
Definition: AlgSequencer.py:30
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:314
ITHistSvc::regTree
virtual StatusCode regTree(const std::string &name)=0
Register a new TTree with a given name.
ISvcLocator
Definition: ISvcLocator.h:46
Algorithm
Alias for backward compatibility.
Definition: Algorithm.h:58
THistWrite::initialize
StatusCode initialize() override
Definition: THistWrite.cpp:39
THistWrite::m_ths
ITHistSvc * m_ths
Definition: THistWrite.h:33
THistWrite::listKeys
void listKeys(TDirectory *td)
Definition: THistWrite.cpp:244
StatusCode
Definition: StatusCode.h:65
Rndm::Gauss
Parameters for the Gauss random number generation.
Definition: RndmGenerators.h:32
LockedHandle.h
ITHistSvc::regHist
virtual StatusCode regHist(const std::string &name)=0
Register a new ROOT histogram TH*X with a name.
ITHistSvc::getHist
virtual StatusCode getHist(const std::string &name, TH1 *&, size_t index=0) const =0
Return histogram with given name as TH1*, THistSvcMT still owns object.
Rndm::Numbers
Random number accessor This small class encapsulates the use of the random number generator.
Definition: RndmGenerators.h:359
AlgSequencer.h
h
Definition: AlgSequencer.py:31
AlgSequencer.p1
p1
Definition: AlgSequencer.py:29
THistWrite
Definition: THistWrite.h:21
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
cpluginsvc.n
n
Definition: cpluginsvc.py:234
ITHistSvc.h
THistWrite.h
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
Gaudi::Units::gauss
constexpr double gauss
Definition: SystemOfUnits.h:252
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
ITHistSvc::regShared
virtual StatusCode regShared(const std::string &name, std::unique_ptr< TH1 >, LockedHandle< TH1 > &)=0
Register shared object of type TH1 and return LockedHandle for that object.
std
STL namespace.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
Gaudi::Algorithm::service
StatusCode service(std::string_view name, T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Algorithm.h:205
ITHistSvc::getShared
virtual StatusCode getShared(const std::string &name, LockedHandle< TH1 > &) const =0
Retrieve shared object with given name as TH1 through LockedHandle.
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
LockedHandle
Definition: LockedHandle.h:38
std::unique_ptr< TH1F >
compareRootHistos.tp
tp
Definition: compareRootHistos.py:489
ProduceConsume.key
key
Definition: ProduceConsume.py:81
ITHistSvc::getTree
virtual StatusCode getTree(const std::string &name, TTree *&) const =0
Return TTree with given name.
MsgStream.h