Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v38r1p1 (ae26267b)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
THistWrite.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 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* h6 = new TH1D( "TempHist6", "Temporary Tree 6", 100, 0., 100. );
103  if ( m_ths->regHist( "TempHist6", std::unique_ptr<TH1D>( h6 ), h6 ).isFailure() ) {
104  error() << "Couldn't register TempHist6" << endmsg;
105  }
106  if ( strcmp( h6->GetName(), "TempHist6" ) ) {
107  error() << "Couldn't use TempHist6 afterwards. getName = " << h6->GetName() << endmsg;
108  }
109 
110  TH1D* h7 = new TH1D( "TempHist7", "Temporary Tree 7", 100, 0., 100. );
111  if ( m_ths->regHist( "TempHist7", h7 ).isFailure() ) { error() << "Couldn't register TempHist7" << endmsg; }
112  if ( strcmp( h7->GetName(), "TempHist7" ) ) {
113  error() << "Couldn't use TempHist7 afterwards. getName = " << h7->GetName() << endmsg;
114  }
115 
116  // Profile in "/"
117  std::unique_ptr<TH1> tp = std::make_unique<TProfile>( "profile", "profile", 100, -50., -50. );
118  if ( m_ths->regHist( "/rec/prof", std::move( tp ) ).isFailure() ) { error() << "Couldn't register prof" << endmsg; }
119 
120  // Tree with branches in "/trees/stuff"
121  std::unique_ptr<TTree> tr = std::make_unique<TTree>( "treename", "tree title" );
122  if ( m_ths->regTree( "/rec/trees/stuff/tree1", std::move( tr ) ).isFailure() ) {
123  error() << "Couldn't register tr" << endmsg;
124  }
125 
126  // Update to stream "upd", dir "/xxx"
127  std::unique_ptr<TH1F> h3s = std::make_unique<TH1F>( "1Dgauss_shared", "1D Gaussian", 100, -50., 50. );
128  LockedHandle<TH1> lh1( nullptr, nullptr );
129  if ( m_ths->regShared( "/upd/xxx/gauss1d_shared", std::move( h3s ), lh1 ).isFailure() ) {
130  error() << "Couldn't register gauss1d_shared" << endmsg;
131  }
132 
133  // Recreate 2D tree in "/"
134  std::unique_ptr<TH2F> h3sa = std::make_unique<TH2F>( "2Dgauss_shared", "2D Gaussian", 100, -50., 50., 100, -50, 50 );
135  LockedHandle<TH2> lh2( nullptr, nullptr );
136  if ( m_ths->regShared( "/rec/gauss2d_shared", std::move( h3sa ), lh2 ).isFailure() ) {
137  error() << "Couldn't register gauss2d_shared" << endmsg;
138  }
139 
140  // 3D tree in "/"
142  std::make_unique<TH3F>( "3Dgauss_shared", "3D Gaussian", 100, -50., 50., 100, -50, 50, 100, -50, 50 );
143  LockedHandle<TH3> lh3( nullptr, nullptr );
144  if ( m_ths->regShared( "/rec/gauss3d_shared", std::move( h4s ), lh3 ).isFailure() ) {
145  error() << "Couldn't register gauss3d_shared" << endmsg;
146  }
147 
148  return StatusCode::SUCCESS;
149 }
150 
151 //------------------------------------------------------------------------------
153 //------------------------------------------------------------------------------
154 {
155  Rndm::Numbers gauss( randSvc(), Rndm::Gauss( 0., 15. ) );
156 
157  static int n = 0;
158 
159  double x = sin( double( n ) ) * 52. + 50.;
160 
161  TH1* h( nullptr );
162  if ( m_ths->getHist( "TempHist1", h ).isSuccess() ) {
163  h->Fill( x );
164  } else {
165  error() << "Couldn't retrieve TempHist 1" << endmsg;
166  }
167 
168  if ( m_ths->getHist( "other/TempHist1a", h ).isSuccess() ) {
169  h->Fill( x );
170  } else {
171  error() << "Couldn't retrieve TempHist 1a" << endmsg;
172  }
173 
174  if ( m_ths->getHist( "/new/Tree2", h ).isSuccess() ) {
175  h->Fill( x );
176  } else {
177  error() << "Couldn't retrieve Tree2" << endmsg;
178  }
179 
180  if ( m_ths->getHist( "/upd/xxx/gauss1d", h ).isSuccess() ) {
181  for ( int i = 0; i < 1000; ++i ) { h->Fill( gauss(), 1. ); }
182  } else {
183  error() << "Couldn't retrieve 1Dgauss" << endmsg;
184  }
185 
186  TH2* h2( nullptr );
187  if ( m_ths->getHist( "/rec/gauss2d", h2 ).isSuccess() ) {
188  for ( int i = 0; i < 1000; ++i ) { h2->Fill( gauss(), gauss(), 1. ); }
189  } else {
190  error() << "Couldn't retrieve 2Dgauss" << endmsg;
191  }
192 
193  TH3* h3( nullptr );
194  if ( m_ths->getHist( "/rec/gauss3d", h3 ).isSuccess() ) {
195  for ( int i = 0; i < 1000; ++i ) { h3->Fill( gauss(), gauss(), gauss(), 1. ); }
196  } else {
197  error() << "Couldn't retrieve 3Dgauss" << endmsg;
198  }
199 
200  if ( m_ths->getHist( "TempHist5", h ).isSuccess() ) {
201  h->Fill( x );
202  } else {
203  error() << "Couldn't retrieve TempHist 5" << endmsg;
204  }
205 
206  if ( m_ths->getHist( "TempHist6", h ).isSuccess() ) {
207  h->Fill( x );
208  } else {
209  error() << "Couldn't retrieve TempHist 6" << endmsg;
210  }
211 
212  LockedHandle<TH1> lh1( nullptr, nullptr );
213  if ( m_ths->getShared( "/upd/xxx/gauss1d_shared", lh1 ).isSuccess() ) {
214  for ( int i = 0; i < 1000; ++i ) { lh1->Fill( gauss(), 1. ); }
215  } else {
216  error() << "Couldn't retrieve 1Dgauss_shared" << endmsg;
217  }
218 
219  LockedHandle<TH2> lh2( nullptr, nullptr );
220  if ( m_ths->getShared( "/rec/gauss2d_shared", lh2 ).isSuccess() ) {
221  for ( int i = 0; i < 1000; ++i ) { lh2->Fill( gauss(), gauss(), 1. ); }
222  } else {
223  error() << "Couldn't retrieve 2Dgauss_shared" << endmsg;
224  }
225 
226  LockedHandle<TH3> lh3( nullptr, nullptr );
227  if ( m_ths->getShared( "/rec/gauss3d_shared", lh3 ).isSuccess() ) {
228  for ( int i = 0; i < 1000; ++i ) { lh3->Fill( gauss(), gauss(), gauss(), 1. ); }
229  } else {
230  error() << "Couldn't retrieve 3Dgauss_shared" << endmsg;
231  }
232 
233  TTree* tr( nullptr );
234  if ( m_ths->getTree( "/rec/trees/stuff/tree1", tr ).isFailure() ) {
235  error() << "Couldn't retrieve tree tree1" << endmsg;
236  } else {
237  if ( n == 0 ) {
238  int p1, p2, p3;
239  tr->Branch( "branch1", &p1, "point1/I" );
240  tr->Branch( "branch2", &p2, "point2/I" );
241  tr->Branch( "branch3", &p3, "point3/I" );
242 
243  for ( int i = 0; i < 1000; i++ ) {
244  p1 = i;
245  p2 = i % 10;
246  p3 = i % 7;
247 
248  tr->Fill();
249  }
250  }
251  }
252 
253  n++;
254  return StatusCode::SUCCESS;
255 }
256 
257 //------------------------------------------------------------------------------
258 void THistWrite::listKeys( TDirectory* td ) {
259  //------------------------------------------------------------------------------
260 
261  info() << "printing keys for: " << td->GetPath() << " (" << td->GetList()->GetSize() << ")" << endmsg;
262  TIter nextkey( td->GetList() );
263  while ( TKey* key = (TKey*)nextkey() ) {
264  if ( key != 0 ) {
265  info() << key->GetName() << " (" << key->IsA()->GetName()
266  << ") "
267  // << key->GetObjectStat()
268  // << " " << key->IsOnHeap()
269  << key->GetCycle() << endmsg;
270  } else {
271  info() << "key == 0" << endmsg;
272  }
273  }
274 
275  return;
276 }
277 
278 //------------------------------------------------------------------------------
280 //------------------------------------------------------------------------------
281 {
282  info() << "Finalizing..." << endmsg;
283 
284  if ( m_ths->deReg( "/temp/TempHist6" ).isFailure() ) {
285  error() << "Failed to deregister histogram TempHist6" << endmsg;
286  }
287 
288  TH1* h7 = nullptr;
289  if ( m_ths->getHist( "TempHist7", h7 ).isFailure() ) { error() << "Couldn't retrieve TempHist7" << endmsg; }
290  if ( m_ths->deReg( h7 ).isFailure() ) { error() << "Failed to deregister histogram TempHist7" << endmsg; }
291 
292  return StatusCode::SUCCESS;
293 }
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:152
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:279
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:258
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
GaudiPluginService.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:76
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
STL class.
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