ATLAS Offline Software
HistogramFactory.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
5 
6 #include "TH1.h"
7 #include "TH2.h"
8 #include "TGraph.h"
9 #include "TProfile.h"
10 #include "TProfile2D.h"
11 #include "TTree.h"
12 #include "TROOT.h"
13 
14 #include "HistogramException.h"
15 #include "HistogramFactory.h"
16 
17 using namespace Monitored;
18 
20  const std::string& histoPath)
21 : m_histSvc(histSvc)
22 {
23  // The Gaudi/offline THistSvc does not delete objects on de-registration,
24  // but the online TrigMonTHistSvc does. We detect the latter case by checking
25  // the existence of one of its properties.
26  SmartIF<IProperty> hs{histSvc.get()};
27  if (hs && hs->hasProperty("IncludeName")) {
28  m_deleteOnRemove = false;
29  }
30 
31  size_t whereToStart = 0;
32  // do we have a leading slash? This distinguishes temporary streams in THistSvc
33  if (! histoPath.empty() && histoPath[0] == '/') {
34  whereToStart = 1;
35  }
36  size_t split = histoPath.find('/', whereToStart);
37  m_streamName = (whereToStart == 1 ? "/" : "") + histoPath.substr(0,split);
38  m_groupName = split!=std::string::npos ? histoPath.substr(split+1) : "";
39  // Infrequently, loading a ROOT class in a MT context can fail.
40  // So try to load the classes we'll need early.
41  TClass::GetClass("TH1F");
42  TClass::GetClass("TH1D");
43  TClass::GetClass("TH1C");
44  TClass::GetClass("TH1S");
45  TClass::GetClass("TH1I");
46  TClass::GetClass("TH2F");
47  TClass::GetClass("TH2D");
48  TClass::GetClass("TH2C");
49  TClass::GetClass("TH2S");
50  TClass::GetClass("TH2I");
51  TClass::GetClass("TProfile");
52  TClass::GetClass("TProfile2D");
53  TClass::GetClass("TEfficiency");
54  TClass::GetClass("TTree");
55 }
56 
57 
59  std::scoped_lock lock(m_createLock);
60  TNamed* rootObj(0);
61 
62  if (def.type == "TH1F") {
63  rootObj = create1D<TH1F>(def);
64  } else if (def.type == "TH1D") {
65  rootObj = create1D<TH1D>(def);
66  } else if (def.type == "TH1C") {
67  rootObj = create1D<TH1C>(def);
68  } else if (def.type == "TH1S") {
69  rootObj = create1D<TH1S>(def);
70  } else if (def.type == "TH1I") {
71  rootObj = create1D<TH1I>(def);
72  } else if (def.type == "TH2F") {
73  rootObj = create2D<TH2F>(def);
74  } else if (def.type == "TH2D") {
75  rootObj = create2D<TH2D>(def);
76  } else if (def.type == "TH2C") {
77  rootObj = create2D<TH2C>(def);
78  } else if (def.type == "TH2S") {
79  rootObj = create2D<TH2S>(def);
80  } else if (def.type == "TH2I") {
81  rootObj = create2D<TH2I>(def);
82  } else if (def.type == "TProfile") {
83  rootObj = create1DProfile<TProfile>(def);
84  } else if (def.type == "TProfile2D") {
85  rootObj = create2DProfile<TProfile2D>(def);
86  } else if (def.type == "TEfficiency") {
88  } else if (def.type == "TTree") {
89  rootObj = createTree(def);
90  }
91 
92  if (rootObj == 0) {
93  throw HistogramException("Can not create yet histogram of type: >" + def.type + "<\n" +
94  "Try one of: TH1[F,D,C,S,I], TH2[F,D,C,S,I], TProfile, TProfile2D, " +
95  "TEfficiency, TTree.");
96  }
97 
98  return rootObj;
99 }
100 
101 template<class H>
103  if ( def.xarray.size()!=0 ) {
104  return create<H,TH1>(def, def.xbins, &(def.xarray)[0]);
105  } else {
106  return create<H,TH1>(def, def.xbins, def.xmin, def.xmax);
107  }
108 }
109 
110 template<class H>
112  if (def.xarray.size()!=0) {
113  return create<H,TH1>(def, def.xbins, &(def.xarray)[0],
114  def.ymin, def.ymax);
115  } else {
116  return create<H,TH1>(def, def.xbins, def.xmin, def.xmax,
117  def.ymin, def.ymax);
118  }
119 }
120 
121 template<class H>
123  if (def.xarray.size()!=0 && def.yarray.size()!=0) {
124  return create<H,TH2>(def, def.xbins, &(def.xarray)[0],
125  def.ybins, &(def.yarray)[0]);
126  } else if (def.yarray.size()!=0) {
127  return create<H,TH2>(def, def.xbins, def.xmin, def.xmax,
128  def.ybins, &(def.yarray)[0]);
129  } else if (def.xarray.size()!=0) {
130  return create<H,TH2>(def, def.xbins, &(def.xarray)[0],
131  def.ybins, def.ymin, def.ymax);
132  } else {
133  return create<H,TH2>(def, def.xbins, def.xmin, def.xmax,
134  def.ybins, def.ymin, def.ymax);
135  }
136 }
137 
138 template<class H>
140  if (def.xarray.size()!=0 && def.yarray.size()!=0) {
141  return create<H,TH2>(def, def.xbins, &(def.xarray)[0],
142  def.ybins, &(def.yarray)[0]);
143  } else if (def.yarray.size()!=0) {
144  return create<H,TH2>(def, def.xbins, def.xmin, def.xmax,
145  def.ybins, &(def.yarray)[0]);
146  } else if (def.xarray.size()!=0) {
147  return create<H,TH2>(def, def.xbins, &(def.xarray)[0],
148  def.ybins, def.ymin, def.ymax);
149  } else {
150  return create<H,TH2>(def, def.xbins, def.xmin, def.xmax,
151  def.ybins, def.ymin, def.ymax,
152  def.zmin, def.zmax);
153  }
154 }
155 
157  std::string fullName = getFullName(def);
158 
159  // Check if efficiency exists already
160  TEfficiency* e = nullptr;
161  if ( m_histSvc->existsEfficiency(fullName) ) {
162  if ( !m_histSvc->getEfficiency(fullName,e) ) {
163  throw HistogramException("Histogram >"+ fullName + "< seems to exist but can not be obtained from THistSvc");
164  }
165  return e;
166  }
167 
168  // Otherwise, create the efficiency and register it
169  // Hold global lock until we have detached object from gDirectory
170  {
171  std::scoped_lock<std::mutex> dirLock(globalROOTMutex());
172  if (def.ybins==0 && def.zbins==0) { // 1D TEfficiency
173  if (def.xarray.size()!=0) {
174  e = new TEfficiency(def.alias.c_str(), def.title.c_str(),
175  def.xbins, &(def.xarray)[0]);
176  } else {
177  e = new TEfficiency(def.alias.c_str(), def.title.c_str(),
178  def.xbins, def.xmin, def.xmax);
179  }
180  } else if (def.ybins>0 && def.zbins==0) { // 2D TEfficiency
181  if (def.xarray.size()!=0 && def.yarray.size()!=0) {
182  e = new TEfficiency(def.alias.c_str(), def.title.c_str(),
183  def.xbins, &(def.xarray)[0], def.ybins, &(def.yarray)[0]);
184  } else {
185  e = new TEfficiency(def.alias.c_str(), def.title.c_str(),
186  def.xbins, def.xmin, def.xmax, def.ybins, def.ymin, def.ymax);
187  }
188  } else if (def.ybins>0 && def.zbins>0) { // 3D TEfficiency
189  e = new TEfficiency(def.alias.c_str(), def.title.c_str(),
190  def.xbins, def.xmin, def.xmax, def.ybins, def.ymin, def.ymax, def.zbins, def.zmin, def.zmax);
191  } else {
192  throw HistogramException("Histogram >"+ fullName + "< could not be defined. Check xbins, ybins, and zbins.");
193  }
194  e->SetDirectory(0);
195  }
196  if ( !m_histSvc->regEfficiency(fullName, std::unique_ptr<TEfficiency>(e)) ) {
197  throw HistogramException("Histogram >"+ fullName + "< can not be registered in THistSvc");
198  }
199  TH1* total ATLAS_THREAD_SAFE = const_cast<TH1*>(e->GetTotalHistogram());
200  setLabels(total, def);
201  TH1* passed ATLAS_THREAD_SAFE = const_cast<TH1*>(e->GetPassedHistogram());
202  setLabels(passed, def);
203 
204  return e;
205 }
206 
207 template<class H, class HBASE, typename... Types>
209  std::string fullName = getFullName(def);
210 
211  // Check if histogram exists already
212  HBASE* histo = nullptr;
213  if ( m_histSvc->exists( fullName ) ) {
214  if ( !m_histSvc->getHist( fullName, histo ) ) {
215  throw HistogramException("Histogram >"+ fullName + "< seems to exist but can not be obtained from THistSvc");
216  }
217  return histo;
218  }
219 
220  // Create the histogram and register it
221  // Hold global lock until we have detached object from gDirectory
222  H* h = nullptr;
223  {
224  std::scoped_lock<std::mutex> dirLock(globalROOTMutex());
225  h = new H(def.alias.c_str(), def.title.c_str(), std::forward<Types>(hargs)...);
226  h->SetDirectory(0);
227  }
228  if ( !m_histSvc->regHist( fullName, std::unique_ptr<TH1>(h) ) ) {
229  throw HistogramException("Histogram >"+ fullName + "< can not be registered in THistSvc");
230  }
231 
232  h->GetYaxis()->SetTitleOffset(1.25); // magic shift to make histograms readable even if no post-procesing is done
233  setLabels(h, def);
234  setOpts(h, def);
235 
236  return h;
237 }
238 
240  std::string fullName = getFullName(def);
241 
242  // Check if tree exists already
243  TTree* t = nullptr;
244  if ( m_histSvc->existsTree(fullName) ) {
245  if ( !m_histSvc->getTree(fullName,t) ) {
246  throw HistogramException("Tree >"+ fullName + "< seems to exist but can not be obtained from THistSvc");
247  }
248  return t;
249  }
250 
251  // Otherwise, create the tree and register it
252  // branches will be created by HistogramFillerTree
253  {
254  std::scoped_lock<std::mutex> dirLock(globalROOTMutex());
255  t = new TTree(def.alias.c_str(),def.title.c_str());
256  t->SetDirectory(0);
257  }
258  if ( !m_histSvc->regTree(fullName, std::unique_ptr<TTree>(t) ) ) {
259  throw HistogramException("Tree >"+ fullName + "< can not be registered in THistSvc");
260  }
261 
262  return t;
263 }
264 
266  // apply extension policy
267  const unsigned canExtendPolicy = def.kCanRebin ? TH1::kAllAxes : TH1::kNoAxis;
268  hist->SetCanExtend(canExtendPolicy);
269 
270  // apply Sumw2 option
271  hist->Sumw2(def.Sumw2);
272 }
273 
275  setLabels(hist->GetXaxis(), def.xlabels);
276  setLabels(hist->GetYaxis(), def.ylabels);
277  setLabels(hist->GetZaxis(), def.zlabels);
278 }
279 
280 void HistogramFactory::setLabels(TAxis* axis, const std::vector<std::string>& labels) {
281  if ( !labels.empty() ) {
282  const int nBin = axis->GetNbins();
283  for ( int bin=0; bin<nBin; bin++ ) {
284  axis->SetBinLabel(bin+1, labels[bin].c_str());
285  }
286  }
287 }
288 
289 namespace {
290  const static std::set<std::string> onlinePaths( { "EXPERT", "SHIFT", "DEBUG", "RUNSTAT", "EXPRESS" } );
291 }
292 std::string HistogramFactory::getFullName(const HistogramDef& def) const {
293 
294  // for online paths, always prepend a slash. Otherwise take it from provided stream name
295  std::string path;
296  if ( onlinePaths.count( def.path)!=0 ) {
297  path = "/" + def.path + "/" + m_streamName + "/" + m_groupName;
298  } else if ( def.path=="DEFAULT" ) {
299  path = "/" + m_streamName + "/" + m_groupName;
300  } else {
301  path = m_streamName + "/" + def.tld + "/" + m_groupName + "/" + def.path;
302  }
303 
304  // remove duplicate slashes
305  std::string fullName = path + "/" + def.alias;
306  fullName.erase( std::unique( fullName.begin(), fullName.end(),
307  [](const char a, const char b) {
308  return a == b and a == '/';
309  } ), fullName.end() );
310 
311  return fullName;
312 }
313 
315  const std::string path = getFullName( def );
316 
317  TObject* obj = nullptr;
318  if (def.type=="TEfficiency") {
319  TEfficiency* e;
320  m_histSvc->getEfficiency(path, e).ignore();
321  obj = e;
322  } else if (def.type=="TGraph") {
323  TGraph* g;
324  m_histSvc->getGraph(path, g).ignore();
325  obj = g;
326  } else if (def.type=="TTree") {
327  TTree* t;
328  m_histSvc->getTree(path, t).ignore();
329  obj = t;
330  } else {
331  TH1* h;
332  m_histSvc->getHist(path, h).ignore();
333  obj = h;
334  }
335 
336  if (obj) {
337  m_histSvc->deReg(path).ignore();
338  if (m_deleteOnRemove) {
339  delete obj;
340  }
341  }
342 }
Monitored::HistogramFactory::m_createLock
std::mutex m_createLock
Definition: HistogramFactory.h:171
Monitored::HistogramFactory::create
virtual TNamed * create(const HistogramDef &def)
Book and register ROOT object for given definition.
Definition: HistogramFactory.cxx:58
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
HistogramException.h
Monitored::HistogramDef::kCanRebin
bool kCanRebin
allow all axes to be rebinned
Definition: HistogramDef.h:47
Monitored::HistogramFactory::m_streamName
std::string m_streamName
defines the stream for THistSvc
Definition: HistogramFactory.h:167
Monitored::HistogramFactory::m_groupName
std::string m_groupName
defines location of group of histograms
Definition: HistogramFactory.h:168
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:128
TrigCompositeUtils::passed
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
Definition: TrigCompositeUtilsRoot.cxx:117
plotmaker.hist
hist
Definition: plotmaker.py:148
WriteCellNoiseToCool.fullName
fullName
Definition: WriteCellNoiseToCool.py:461
yodamerge_tmp.axis
list axis
Definition: yodamerge_tmp.py:241
Monitored::HistogramDef::zmax
float zmax
z axis maximum
Definition: HistogramDef.h:71
bin
Definition: BinsDiffFromStripMedian.h:43
Monitored::HistogramException
Represents error occurred during accessing histograms objects.
Definition: HistogramException.h:14
Monitored::HistogramFactory::create1D
TH1 * create1D(const HistogramDef &def)
Helper for generic 'create' method for 1D histograms.
Definition: HistogramFactory.cxx:102
Monitored::HistogramDef::xbins
int xbins
number of y bins
Definition: HistogramDef.h:55
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Monitored::HistogramDef::ylabels
std::vector< std::string > ylabels
labels for y axis
Definition: HistogramDef.h:65
Monitored::HistogramDef
the internal class used to keep parsed Filler properties
Definition: HistogramDef.h:15
D3PD::Types
std::tuple< WrapType< TYPES >... > Types
A simple tuple of multiple types.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerUtils/D3PDMakerUtils/Types.h:61
Monitored::HistogramDef::yarray
std::vector< double > yarray
array of y bin edges
Definition: HistogramDef.h:66
Monitored::HistogramDef::tld
std::string tld
top level directory (below THistSvc stream)
Definition: HistogramDef.h:22
Monitored::HistogramFactory::setOpts
static void setOpts(TH1 *hist, const HistogramDef &def)
Setup various histogram options.
Definition: HistogramFactory.cxx:265
Monitored::HistogramFactory::create2DProfile
TH2 * create2DProfile(const HistogramDef &def)
Helper for generic 'create' method for 2DProfile histograms.
Definition: HistogramFactory.cxx:139
Monitored::HistogramFactory::m_histSvc
ServiceHandle< ITHistSvc > m_histSvc
Definition: HistogramFactory.h:166
Monitored::HistogramDef::xarray
std::vector< double > xarray
array of x bin edges
Definition: HistogramDef.h:59
Monitored::HistogramDef::xmax
float xmax
x axis maximum
Definition: HistogramDef.h:57
beamspotnt.labels
list labels
Definition: bin/beamspotnt.py:1447
H
#define H(x, y, z)
Definition: MD5.cxx:114
Monitored::HistogramDef::zbins
int zbins
number of z bins
Definition: HistogramDef.h:69
Monitored::HistogramDef::path
std::string path
booking path
Definition: HistogramDef.h:19
Monitored::HistogramDef::ymax
float ymax
y axis maximum
Definition: HistogramDef.h:64
Monitored::HistogramFactory::setLabels
static void setLabels(TH1 *hist, const HistogramDef &def)
Set labels for all axes.
Definition: HistogramFactory.cxx:274
CreatePhysValWebPage.hs
hs
Definition: CreatePhysValWebPage.py:107
Monitored
Generic monitoring tool for athena components.
Definition: GenericMonitoringTool.h:30
h
python.CaloCondTools.g
g
Definition: CaloCondTools.py:15
extractSporadic.h
list h
Definition: extractSporadic.py:97
PyPoolBrowser.rootObj
rootObj
Definition: PyPoolBrowser.py:111
Monitored::HistogramDef::xlabels
std::vector< std::string > xlabels
labels for x axis
Definition: HistogramDef.h:58
Monitored::HistogramFactory::getFullName
std::string getFullName(const HistogramDef &def) const
Invent path name.
Definition: HistogramFactory.cxx:292
Monitored::HistogramDef::xmin
float xmin
x axis minimum
Definition: HistogramDef.h:56
Monitored::HistogramFactory::HistogramFactory
HistogramFactory(const ServiceHandle< ITHistSvc > &histSvc, const std::string &groupName)
Default constructor.
Definition: HistogramFactory.cxx:19
MuonSegmentReaderConfig.histSvc
histSvc
Definition: MuonSegmentReaderConfig.py:96
Monitored::HistogramDef::Sumw2
bool Sumw2
store sum of squares of weights
Definition: HistogramDef.h:43
Monitored::HistogramDef::alias
std::string alias
unique alias for THistSvc
Definition: HistogramDef.h:17
Monitored::HistogramDef::ymin
float ymin
y axis minimum
Definition: HistogramDef.h:63
Monitored::HistogramFactory::create1DProfile
TH1 * create1DProfile(const HistogramDef &def)
Helper for generic 'create' method for 1DProfile histograms.
Definition: HistogramFactory.cxx:111
Monitored::HistogramFactory::create2D
TH2 * create2D(const HistogramDef &def)
Helper for generic 'create' method for 2D histograms.
Definition: HistogramFactory.cxx:122
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Monitored::HistogramFactory::m_deleteOnRemove
bool m_deleteOnRemove
delete histogram during remove
Definition: HistogramFactory.h:170
Monitored::HistogramFactory::createTree
TTree * createTree(const HistogramDef &def)
Create and register tree.
Definition: HistogramFactory.cxx:239
Monitored::HistogramDef::type
std::string type
class name
Definition: HistogramDef.h:18
Monitored::HistogramFactory::globalROOTMutex
static std::mutex & globalROOTMutex()
Definition: HistogramFactory.h:68
HistogramFactory.h
a
TList * a
Definition: liststreamerinfos.cxx:10
sim_check_batch.hargs
list hargs
Definition: sim_check_batch.py:226
Monitored::HistogramDef::zmin
float zmin
z axis minimum
Definition: HistogramDef.h:70
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
Monitored::HistogramDef::ybins
int ybins
number of y bins
Definition: HistogramDef.h:62
plotBeamSpotCompare.histo
histo
Definition: plotBeamSpotCompare.py:415
checker_macros.h
Define macros for attributes used to control the static checker.
python.PyAthena.obj
obj
Definition: PyAthena.py:132
Monitored::HistogramFactory::remove
virtual void remove(const HistogramDef &def)
Removes histogram (used to get rid of old LB tagged histograms)
Definition: HistogramFactory.cxx:314
Monitored::HistogramDef::title
std::string title
title of the histogram
Definition: HistogramDef.h:20
Monitored::HistogramDef::zlabels
std::vector< std::string > zlabels
labels for z axis
Definition: HistogramDef.h:72
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
ServiceHandle< ITHistSvc >
Monitored::HistogramFactory::createEfficiency
TEfficiency * createEfficiency(const HistogramDef &def)
Create and register efficiency graph.
Definition: HistogramFactory.cxx:156