The Gaudi Framework  master (37c0b60a)
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 //------------------------------------------------------------------------------
35 {}
36 
37 //------------------------------------------------------------------------------
39 //------------------------------------------------------------------------------
40 {
41 
42  // FIXME - Code here generates a lot of memory leak errors with the leak sanitizers, e.g.
43  //
44  // clang-format off
45  // Indirect leak of 816 byte(s) in 1 object(s) allocated from:
46  // #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
47  // #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
48  // #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
49  // #3 0x7f817782ab5d in THistWrite::initialize() ../GaudiTestSuite/src/THist/THistWrite.cpp:94
50  // clang-format on
51  //
52  // These leaks are currently suppressed in Gaudi/job/Gaudi-LSan.supp - remove entry there to reactivate
53 
54  if ( m_ths.retrieve().isFailure() ) {
55  error() << "Couldn't get THistSvc" << endmsg;
56  return StatusCode::FAILURE;
57  }
58 
59  // Temporary Trees
60  std::unique_ptr<TH1F> h1 = std::make_unique<TH1F>( "TempHist1", "Temporary Tree 1", 100, 0., 100. );
61  if ( m_ths->regHist( "TempHist1", std::move( h1 ) ).isFailure() ) {
62  error() << "Couldn't register TempHist1" << endmsg;
63  }
64 
65  std::unique_ptr<TH1F> h1a = std::make_unique<TH1F>( "TempHist1a", "Temporary Tree 1a", 100, 0., 100. );
66  if ( m_ths->regHist( "other/TempHist1a", std::move( h1a ) ).isFailure() ) {
67  error() << "Couldn't register TempHist1a" << endmsg;
68  }
69 
70  // Write to stream "new"
71  std::unique_ptr<TH1F> h2 = std::make_unique<TH1F>( "Tree2", "Tree 2", 100, 0., 100. );
72  if ( m_ths->regHist( "/new/Tree2", std::move( h2 ) ).isFailure() ) { error() << "Couldn't register Tree2" << endmsg; }
73 
74  // Update to stream "upd", dir "/xxx"
75  std::unique_ptr<TH1F> h3 = std::make_unique<TH1F>( "1Dgauss", "1D Gaussian", 100, -50., 50. );
76  if ( m_ths->regHist( "/upd/xxx/gauss1d", std::move( h3 ) ).isFailure() ) {
77  error() << "Couldn't register gauss1d" << endmsg;
78  }
79 
80  // Recreate 2D tree in "/"
81  std::unique_ptr<TH2F> h3a = std::make_unique<TH2F>( "2Dgauss", "2D Gaussian", 100, -50., 50., 100, -50, 50 );
82  if ( m_ths->regHist( "/rec/gauss2d", std::move( h3a ) ).isFailure() ) {
83  error() << "Couldn't register gauss2d" << endmsg;
84  }
85 
86  // 3D tree in "/"
88  std::make_unique<TH3F>( "3Dgauss", "3D Gaussian", 100, -50., 50., 100, -50, 50, 100, -50, 50 );
89  if ( m_ths->regHist( "/rec/gauss3d", std::move( h4 ) ).isFailure() ) {
90  error() << "Couldn't register gauss3d" << endmsg;
91  }
92 
93  TH1F* h5 = new TH1F( "TempHist5", "Temporary Tree 5", 100, 0., 100. );
94  if ( m_ths->regHist( "TempHist5", std::unique_ptr<TH1F>( h5 ) ).isFailure() ) {
95  error() << "Couldn't register TempHist5" << endmsg;
96  }
97  if ( strcmp( h5->GetName(), "TempHist5" ) ) {
98  error() << "Couldn't use TempHist5 afterwards. getName = " << h5->GetName() << endmsg;
99  }
100 
101  TH1D* h7 = new TH1D( "TempHist7", "Temporary Tree 7", 100, 0., 100. );
102  if ( m_ths->regHist( "TempHist7", h7 ).isFailure() ) { error() << "Couldn't register TempHist7" << endmsg; }
103  if ( strcmp( h7->GetName(), "TempHist7" ) ) {
104  error() << "Couldn't use TempHist7 afterwards. getName = " << h7->GetName() << endmsg;
105  }
106 
107  // Profile in "/"
108  std::unique_ptr<TH1> tp = std::make_unique<TProfile>( "profile", "profile", 100, -50., -50. );
109  if ( m_ths->regHist( "/rec/prof", std::move( tp ) ).isFailure() ) { error() << "Couldn't register prof" << endmsg; }
110 
111  // Tree with branches in "/trees/stuff"
112  std::unique_ptr<TTree> tr = std::make_unique<TTree>( "treename", "tree title" );
113  if ( m_ths->regTree( "/rec/trees/stuff/tree1", std::move( tr ) ).isFailure() ) {
114  error() << "Couldn't register tr" << endmsg;
115  }
116 
117  // Update to stream "upd", dir "/xxx"
118  std::unique_ptr<TH1F> h3s = std::make_unique<TH1F>( "1Dgauss_shared", "1D Gaussian", 100, -50., 50. );
119  LockedHandle<TH1> lh1( nullptr, nullptr );
120  if ( m_ths->regShared( "/upd/xxx/gauss1d_shared", std::move( h3s ), lh1 ).isFailure() ) {
121  error() << "Couldn't register gauss1d_shared" << endmsg;
122  }
123 
124  // Recreate 2D tree in "/"
125  std::unique_ptr<TH2F> h3sa = std::make_unique<TH2F>( "2Dgauss_shared", "2D Gaussian", 100, -50., 50., 100, -50, 50 );
126  LockedHandle<TH2> lh2( nullptr, nullptr );
127  if ( m_ths->regShared( "/rec/gauss2d_shared", std::move( h3sa ), lh2 ).isFailure() ) {
128  error() << "Couldn't register gauss2d_shared" << endmsg;
129  }
130 
131  // 3D tree in "/"
133  std::make_unique<TH3F>( "3Dgauss_shared", "3D Gaussian", 100, -50., 50., 100, -50, 50, 100, -50, 50 );
134  LockedHandle<TH3> lh3( nullptr, nullptr );
135  if ( m_ths->regShared( "/rec/gauss3d_shared", std::move( h4s ), lh3 ).isFailure() ) {
136  error() << "Couldn't register gauss3d_shared" << endmsg;
137  }
138 
139  return StatusCode::SUCCESS;
140 }
141 
142 //------------------------------------------------------------------------------
144 //------------------------------------------------------------------------------
145 {
146  Rndm::Numbers gauss( randSvc(), Rndm::Gauss( 0., 15. ) );
147 
148  static int n = 0;
149 
150  double x = sin( double( n ) ) * 52. + 50.;
151 
152  TH1* h( nullptr );
153  if ( m_ths->getHist( "TempHist1", h ).isSuccess() ) {
154  h->Fill( x );
155  } else {
156  error() << "Couldn't retrieve TempHist 1" << endmsg;
157  }
158 
159  if ( m_ths->getHist( "other/TempHist1a", h ).isSuccess() ) {
160  h->Fill( x );
161  } else {
162  error() << "Couldn't retrieve TempHist 1a" << endmsg;
163  }
164 
165  if ( m_ths->getHist( "/new/Tree2", h ).isSuccess() ) {
166  h->Fill( x );
167  } else {
168  error() << "Couldn't retrieve Tree2" << endmsg;
169  }
170 
171  if ( m_ths->getHist( "/upd/xxx/gauss1d", h ).isSuccess() ) {
172  for ( int i = 0; i < 1000; ++i ) { h->Fill( gauss(), 1. ); }
173  } else {
174  error() << "Couldn't retrieve 1Dgauss" << endmsg;
175  }
176 
177  TH2* h2( nullptr );
178  if ( m_ths->getHist( "/rec/gauss2d", h2 ).isSuccess() ) {
179  for ( int i = 0; i < 1000; ++i ) { h2->Fill( gauss(), gauss(), 1. ); }
180  } else {
181  error() << "Couldn't retrieve 2Dgauss" << endmsg;
182  }
183 
184  TH3* h3( nullptr );
185  if ( m_ths->getHist( "/rec/gauss3d", h3 ).isSuccess() ) {
186  for ( int i = 0; i < 1000; ++i ) { h3->Fill( gauss(), gauss(), gauss(), 1. ); }
187  } else {
188  error() << "Couldn't retrieve 3Dgauss" << endmsg;
189  }
190 
191  if ( m_ths->getHist( "TempHist5", h ).isSuccess() ) {
192  h->Fill( x );
193  } else {
194  error() << "Couldn't retrieve TempHist 5" << endmsg;
195  }
196 
197  LockedHandle<TH1> lh1( nullptr, nullptr );
198  if ( m_ths->getShared( "/upd/xxx/gauss1d_shared", lh1 ).isSuccess() ) {
199  for ( int i = 0; i < 1000; ++i ) { lh1->Fill( gauss(), 1. ); }
200  } else {
201  error() << "Couldn't retrieve 1Dgauss_shared" << endmsg;
202  }
203 
204  LockedHandle<TH2> lh2( nullptr, nullptr );
205  if ( m_ths->getShared( "/rec/gauss2d_shared", lh2 ).isSuccess() ) {
206  for ( int i = 0; i < 1000; ++i ) { lh2->Fill( gauss(), gauss(), 1. ); }
207  } else {
208  error() << "Couldn't retrieve 2Dgauss_shared" << endmsg;
209  }
210 
211  LockedHandle<TH3> lh3( nullptr, nullptr );
212  if ( m_ths->getShared( "/rec/gauss3d_shared", lh3 ).isSuccess() ) {
213  for ( int i = 0; i < 1000; ++i ) { lh3->Fill( gauss(), gauss(), gauss(), 1. ); }
214  } else {
215  error() << "Couldn't retrieve 3Dgauss_shared" << endmsg;
216  }
217 
218  TTree* tr( nullptr );
219  if ( m_ths->getTree( "/rec/trees/stuff/tree1", tr ).isFailure() ) {
220  error() << "Couldn't retrieve tree tree1" << endmsg;
221  } else {
222  if ( n == 0 ) {
223  int p1, p2, p3;
224  tr->Branch( "branch1", &p1, "point1/I" );
225  tr->Branch( "branch2", &p2, "point2/I" );
226  tr->Branch( "branch3", &p3, "point3/I" );
227 
228  for ( int i = 0; i < 1000; i++ ) {
229  p1 = i;
230  p2 = i % 10;
231  p3 = i % 7;
232 
233  tr->Fill();
234  }
235  }
236  }
237 
238  n++;
239  return StatusCode::SUCCESS;
240 }
241 
242 //------------------------------------------------------------------------------
243 void THistWrite::listKeys( TDirectory* td ) {
244  //------------------------------------------------------------------------------
245 
246  info() << "printing keys for: " << td->GetPath() << " (" << td->GetList()->GetSize() << ")" << endmsg;
247  TIter nextkey( td->GetList() );
248  while ( TKey* key = (TKey*)nextkey() ) {
249  if ( key != 0 ) {
250  info() << key->GetName() << " (" << key->IsA()->GetName()
251  << ") "
252  // << key->GetObjectStat()
253  // << " " << key->IsOnHeap()
254  << key->GetCycle() << endmsg;
255  } else {
256  info() << "key == 0" << endmsg;
257  }
258  }
259 
260  return;
261 }
262 
263 //------------------------------------------------------------------------------
265 //------------------------------------------------------------------------------
266 {
267  info() << "Finalizing..." << endmsg;
268 
269  TH1* h7 = nullptr;
270  if ( m_ths->getHist( "TempHist7", h7 ).isFailure() ) { error() << "Couldn't retrieve TempHist7" << endmsg; }
271  if ( m_ths->deReg( h7 ).isFailure() ) { error() << "Failed to deregister histogram TempHist7" << endmsg; }
272 
273  return StatusCode::SUCCESS;
274 }
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:143
RndmGenerators.h
Gaudi::Algorithm::randSvc
SmartIF< IRndmGenSvc > & randSvc() const
The standard RandomGen service, Return a pointer to the service if present.
Definition: Algorithm.cpp:563
THistWrite::finalize
StatusCode finalize() override
Definition: THistWrite.cpp:264
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:38
THistWrite::listKeys
void listKeys(TDirectory *td)
Definition: THistWrite.cpp:243
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:22
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
ServiceHandle::retrieve
StatusCode retrieve(T *&service) const override
Do the real retrieval of the Service.
Definition: ServiceHandle.h:97
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
THistWrite::m_ths
ServiceHandle< ITHistSvc > m_ths
Definition: THistWrite.h:34
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:84
ITHistSvc::getTree
virtual StatusCode getTree(const std::string &name, TTree *&) const =0
Return TTree with given name.
MsgStream.h