Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
Channel.cxx
Go to the documentation of this file.
1// @(#)root/roostats:$Id$
2// Author: Kyle Cranmer, George Lewis
3/*************************************************************************
4 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11////////////////////////////////////////////////////////////////////////////////
12/** \class RooStats::HistFactory::Channel
13 * \ingroup HistFactory
14 This class encapsulates all information for the statistical interpretation of one experiment.
15 It can be combined with other channels (e.g. for the combination of multiple experiments, or
16 to constrain nuisance parameters with information obtained in a control region).
17 A channel contains one or more samples which describe the contribution from different processes
18 to this measurement.
19*/
20
21
22
24#include "HFMsgService.h"
25#include <cstdlib>
26
27#include "TFile.h"
28#include "TKey.h"
29#include "TTimeStamp.h"
30
32
33using namespace std;
34
36 fName( "" )
37{
38 // standard constructor
39}
40
42 fName( other.fName ),
43 fInputFile( other.fInputFile ),
44 fHistoPath( other.fHistoPath ),
45 fData( other.fData ),
46 fAdditionalData( other.fAdditionalData ),
47 fStatErrorConfig( other.fStatErrorConfig ),
48 fSamples( other.fSamples )
49{ ; }
50
51
52RooStats::HistFactory::Channel::Channel(std::string ChanName, std::string ChanInputFile) :
53 fName( ChanName ), fInputFile( ChanInputFile )
54{
55 // create channel with given name and input file
56}
57
58namespace RooStats{
59 namespace HistFactory{
60 //BadChannel = Channel();
62 // BadChannel.Name = "BadChannel"; // = Channel(); //.Name = "BadChannel";
63 }
64}
65
66
68{
69 // add fully configured sample to channel
70
71 sample.SetChannelName( GetName() );
72 fSamples.push_back( sample );
73}
74
75void RooStats::HistFactory::Channel::Print( std::ostream& stream ) {
76 // print information of channel to given stream
77
78 stream << "\t Channel Name: " << fName
79 << "\t InputFile: " << fInputFile
80 << std::endl;
81
82 stream << "\t Data:" << std::endl;
83 fData.Print( stream );
84
85
86 stream << "\t statErrorConfig:" << std::endl;
87 fStatErrorConfig.Print( stream );
88
89
90 if( !fSamples.empty() ) {
91
92 stream << "\t Samples: " << std::endl;
93 for( unsigned int i = 0; i < fSamples.size(); ++i ) {
94 fSamples.at(i).Print( stream );
95 }
96 }
97
98
99 stream << "\t End of Channel " << fName << std::endl;
100
101
102}
103
104
105void RooStats::HistFactory::Channel::PrintXML( std::string const& directory, std::string const& prefix ) const {
106
107 // Create an XML file for this channel
108 cxcoutPHF << "Printing XML Files for channel: " << GetName() << std::endl;
109
110 std::string XMLName = prefix + fName + ".xml";
111 if(!directory.empty()) XMLName = directory + "/" + XMLName;
112
113 ofstream xml( XMLName.c_str() );
114
115 // Add the time
116 xml << "<!--" << std::endl;
117 xml << "This xml file created automatically on: " << std::endl;
118 // LM: use TTimeStamp since time_t does not work on Windows
119 TTimeStamp t;
120 UInt_t year = 0;
121 UInt_t month = 0;
122 UInt_t day = 0;
123 t.GetDate(true, 0, &year, &month, &day);
124 xml << year << '-'
125 << month << '-'
126 << day
127 << std::endl;
128 xml << "-->" << std::endl;
129
130 // Add the DOCTYPE
131 xml << "<!DOCTYPE Channel SYSTEM 'HistFactorySchema.dtd'> " << std::endl << std::endl;
132
133 // Add the Channel
134 xml << " <Channel Name=\"" << fName << "\" InputFile=\"" << fInputFile << "\" >" << std::endl << std::endl;
135
136 fData.PrintXML( xml );
137 for(auto const& data : fAdditionalData) {
138 data.PrintXML(xml);
139 }
140
141 fStatErrorConfig.PrintXML( xml );
142 /*
143 xml << " <StatErrorConfig RelErrorThreshold=\"" << fStatErrorConfig.GetRelErrorThreshold() << "\" "
144 << "ConstraintType=\"" << Constraint::Name( fStatErrorConfig.GetConstraintType() ) << "\" "
145 << "/> " << std::endl << std::endl;
146 */
147
148 for(auto const& sample : fSamples) {
149 sample.PrintXML( xml );
150 xml << std::endl << std::endl;
151 }
152
153 xml << std::endl;
154 xml << " </Channel> " << std::endl;
155 xml.close();
156
157 cxcoutPHF << "Finished printing XML files" << std::endl;
158
159}
160
161
162void RooStats::HistFactory::Channel::SetData( std::string DataHistoName, std::string DataInputFile, std::string DataHistoPath ) {
163 // set data for this channel by specifying the name of the histogram,
164 // the external ROOT file and the path to the histogram inside the ROOT file
165
166 fData.SetHistoName( DataHistoName );
167 fData.SetInputFile( DataInputFile );
168 fData.SetHistoPath( DataHistoPath );
169
170}
171
172
173
175 // set data directly to some histogram
176 fData.SetHisto( hData );
177}
178
180
181 // For a NumberCounting measurement only
182 // Set the value of data in a particular channel
183 //
184 // Internally, this simply creates a 1-bin TH1F for you
185
186 std::string DataHistName = fName + "_data";
187
188 // Histogram has 1-bin (hard-coded)
189 TH1F* hData = new TH1F( DataHistName.c_str(), DataHistName.c_str(), 1, 0, 1 );
190 hData->SetBinContent( 1, val );
191
192 // Set the histogram of the internally held data
193 // node of this channel to this newly created histogram
194 SetData( hData );
195
196}
197
198
199void RooStats::HistFactory::Channel::SetStatErrorConfig( double StatRelErrorThreshold, Constraint::Type StatConstraintType ) {
200
201 fStatErrorConfig.SetRelErrorThreshold( StatRelErrorThreshold );
202 fStatErrorConfig.SetConstraintType( StatConstraintType );
203
204}
205
206void RooStats::HistFactory::Channel::SetStatErrorConfig( double StatRelErrorThreshold, std::string StatConstraintType ) {
207
208 fStatErrorConfig.SetRelErrorThreshold( StatRelErrorThreshold );
209 fStatErrorConfig.SetConstraintType( Constraint::GetType(StatConstraintType) );
210
211}
212
213
214
216
217 // Loop through all Samples and Systematics
218 // and collect all necessary histograms
219
220 // Handles to open files for collecting histograms
221 std::map<std::string,std::unique_ptr<TFile>> fileHandles;
222
223 // Get the Data Histogram:
224
225 if( !fData.GetInputFile().empty() ) {
226 fData.SetHisto( GetHistogram(fData.GetInputFile(),
227 fData.GetHistoPath(),
228 fData.GetHistoName(),
229 fileHandles) );
230 }
231
232 // Collect any histograms for additional Datasets
233 for(auto& data : fAdditionalData) {
234 if( !data.GetInputFile().empty() ) {
235 data.SetHisto( GetHistogram(data.GetInputFile(), data.GetHistoPath(), data.GetHistoName(), fileHandles) );
236 }
237 }
238
239 // Get the histograms for the samples:
240 for( unsigned int sampItr = 0; sampItr < fSamples.size(); ++sampItr ) {
241
242 RooStats::HistFactory::Sample& sample = fSamples.at( sampItr );
243
244
245 // Get the nominal histogram:
246 cxcoutDHF << "Collecting Nominal Histogram" << std::endl;
247 TH1* Nominal = GetHistogram(sample.GetInputFile(),
248 sample.GetHistoPath(),
249 sample.GetHistoName(),
250 fileHandles);
251
252 sample.SetHisto( Nominal );
253
254
255 // Get the StatError Histogram (if necessary)
256 if( sample.GetStatError().GetUseHisto() ) {
257 sample.GetStatError().SetErrorHist( GetHistogram(sample.GetStatError().GetInputFile(),
258 sample.GetStatError().GetHistoPath(),
259 sample.GetStatError().GetHistoName(),
260 fileHandles) );
261 }
262
263
264 // Get the HistoSys Variations:
265 for( unsigned int histoSysItr = 0; histoSysItr < sample.GetHistoSysList().size(); ++histoSysItr ) {
266
267 RooStats::HistFactory::HistoSys& histoSys = sample.GetHistoSysList().at( histoSysItr );
268
269 histoSys.SetHistoLow( GetHistogram(histoSys.GetInputFileLow(),
270 histoSys.GetHistoPathLow(),
271 histoSys.GetHistoNameLow(),
272 fileHandles) );
273
274 histoSys.SetHistoHigh( GetHistogram(histoSys.GetInputFileHigh(),
275 histoSys.GetHistoPathHigh(),
276 histoSys.GetHistoNameHigh(),
277 fileHandles) );
278 } // End Loop over HistoSys
279
280
281 // Get the HistoFactor Variations:
282 for( unsigned int histoFactorItr = 0; histoFactorItr < sample.GetHistoFactorList().size(); ++histoFactorItr ) {
283
284 RooStats::HistFactory::HistoFactor& histoFactor = sample.GetHistoFactorList().at( histoFactorItr );
285
286 histoFactor.SetHistoLow( GetHistogram(histoFactor.GetInputFileLow(),
287 histoFactor.GetHistoPathLow(),
288 histoFactor.GetHistoNameLow(),
289 fileHandles) );
290
291 histoFactor.SetHistoHigh( GetHistogram(histoFactor.GetInputFileHigh(),
292 histoFactor.GetHistoPathHigh(),
293 histoFactor.GetHistoNameHigh(),
294 fileHandles) );
295 } // End Loop over HistoFactor
296
297
298 // Get the ShapeSys Variations:
299 for( unsigned int shapeSysItr = 0; shapeSysItr < sample.GetShapeSysList().size(); ++shapeSysItr ) {
300
301 RooStats::HistFactory::ShapeSys& shapeSys = sample.GetShapeSysList().at( shapeSysItr );
302
303 shapeSys.SetErrorHist( GetHistogram(shapeSys.GetInputFile(),
304 shapeSys.GetHistoPath(),
305 shapeSys.GetHistoName(),
306 fileHandles) );
307 } // End Loop over ShapeSys
308
309
310 // Get any initial shape for a ShapeFactor
311 for( unsigned int shapeFactorItr = 0; shapeFactorItr < sample.GetShapeFactorList().size(); ++shapeFactorItr ) {
312
313 RooStats::HistFactory::ShapeFactor& shapeFactor = sample.GetShapeFactorList().at( shapeFactorItr );
314
315 // Check if we need an InitialShape
316 if( shapeFactor.HasInitialShape() ) {
317 TH1* hist = GetHistogram( shapeFactor.GetInputFile(), shapeFactor.GetHistoPath(),
318 shapeFactor.GetHistoName(), fileHandles );
319 shapeFactor.SetInitialShape( hist );
320 }
321
322 } // End Loop over ShapeFactor
323
324 } // End Loop over Samples
325}
326
327
329
330 // Check that all internal histogram pointers
331 // are properly configured (ie that they're not nullptr)
332
333 if( fData.GetHisto() == nullptr && !fData.GetInputFile().empty() ) {
334 cxcoutEHF << "Error: Data Histogram for channel " << GetName() << " is nullptr." << std::endl;
335 return false;
336 }
337
338 // Get the histograms for the samples:
339 for( unsigned int sampItr = 0; sampItr < fSamples.size(); ++sampItr ) {
340
341 const RooStats::HistFactory::Sample& sample = fSamples.at( sampItr );
342
343 // Get the nominal histogram:
344 if( sample.GetHisto() == nullptr ) {
345 cxcoutEHF << "Error: Nominal Histogram for sample " << sample.GetName() << " is nullptr." << std::endl;
346 return false;
347 }
348 else {
349
350 // Check if any bins are negative
351 std::vector<int> NegativeBinNumber;
352 std::vector<double> NegativeBinContent;
353 const TH1* histNominal = sample.GetHisto();
354 for(int ibin=1; ibin<=histNominal->GetNbinsX(); ++ibin) {
355 if(histNominal->GetBinContent(ibin) < 0) {
356 NegativeBinNumber.push_back(ibin);
357 NegativeBinContent.push_back(histNominal->GetBinContent(ibin));
358 }
359 }
360 if(!NegativeBinNumber.empty()) {
361 cxcoutWHF << "WARNING: Nominal Histogram " << histNominal->GetName() << " for Sample = " << sample.GetName()
362 << " in Channel = " << GetName() << " has negative entries in bin numbers = ";
363
364 for(unsigned int ibin=0; ibin<NegativeBinNumber.size(); ++ibin) {
365 if(ibin>0) std::cout << " , " ;
366 std::cout << NegativeBinNumber[ibin] << " : " << NegativeBinContent[ibin] ;
367 }
368 std::cout << std::endl;
369 }
370
371 }
372
373 // Get the StatError Histogram (if necessary)
374 if( sample.GetStatError().GetUseHisto() ) {
375 if( sample.GetStatError().GetErrorHist() == nullptr ) {
376 cxcoutEHF << "Error: Statistical Error Histogram for sample " << sample.GetName() << " is nullptr." << std::endl;
377 return false;
378 }
379 }
380
381
382 // Get the HistoSys Variations:
383 for( unsigned int histoSysItr = 0; histoSysItr < sample.GetHistoSysList().size(); ++histoSysItr ) {
384
385 const RooStats::HistFactory::HistoSys& histoSys = sample.GetHistoSysList().at( histoSysItr );
386
387 if( histoSys.GetHistoLow() == nullptr ) {
388 cxcoutEHF << "Error: HistoSyst Low for Systematic " << histoSys.GetName()
389 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
390 return false;
391 }
392 if( histoSys.GetHistoHigh() == nullptr ) {
393 cxcoutEHF << "Error: HistoSyst High for Systematic " << histoSys.GetName()
394 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
395 return false;
396 }
397
398 } // End Loop over HistoSys
399
400
401 // Get the HistoFactor Variations:
402 for( unsigned int histoFactorItr = 0; histoFactorItr < sample.GetHistoFactorList().size(); ++histoFactorItr ) {
403
404 const RooStats::HistFactory::HistoFactor& histoFactor = sample.GetHistoFactorList().at( histoFactorItr );
405
406 if( histoFactor.GetHistoLow() == nullptr ) {
407 cxcoutEHF << "Error: HistoSyst Low for Systematic " << histoFactor.GetName()
408 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
409 return false;
410 }
411 if( histoFactor.GetHistoHigh() == nullptr ) {
412 cxcoutEHF << "Error: HistoSyst High for Systematic " << histoFactor.GetName()
413 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
414 return false;
415 }
416
417 } // End Loop over HistoFactor
418
419
420 // Get the ShapeSys Variations:
421 for( unsigned int shapeSysItr = 0; shapeSysItr < sample.GetShapeSysList().size(); ++shapeSysItr ) {
422
423 const RooStats::HistFactory::ShapeSys& shapeSys = sample.GetShapeSysList().at( shapeSysItr );
424
425 if( shapeSys.GetErrorHist() == nullptr ) {
426 cxcoutEHF << "Error: HistoSyst High for Systematic " << shapeSys.GetName()
427 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
428 return false;
429 }
430
431 } // End Loop over ShapeSys
432
433 } // End Loop over Samples
434
435 return true;
436}
437
438
439
440/// Open a file and copy a histogram
441/// \param InputFile File where the histogram resides.
442/// \param HistoPath Path of the histogram in the file.
443/// \param HistoName Name of the histogram to retrieve.
444/// \param lsof List of open files. Helps to prevent opening and closing a file hundreds of times.
445TH1* RooStats::HistFactory::Channel::GetHistogram(std::string InputFile, std::string HistoPath, std::string HistoName, std::map<std::string,std::unique_ptr<TFile>>& lsof) {
446
447 cxcoutPHF << "Getting histogram " << InputFile << ":" << HistoPath << "/" << HistoName << std::endl;
448
449 auto& inFile = lsof[InputFile];
450 if (!inFile || !inFile->IsOpen()) {
451 inFile.reset( TFile::Open(InputFile.c_str()) );
452 if ( !inFile || !inFile->IsOpen() ) {
453 cxcoutEHF << "Error: Unable to open input file: " << InputFile << std::endl;
454 throw hf_exc();
455 }
456 cxcoutIHF << "Opened input file: " << InputFile << ": " << std::endl;
457 }
458
459 TDirectory* dir = inFile->GetDirectory(HistoPath.c_str());
460 if (dir == nullptr) {
461 cxcoutEHF << "Histogram path '" << HistoPath
462 << "' wasn't found in file '" << InputFile << "'." << std::endl;
463 throw hf_exc();
464 }
465
466 // Have to read histograms via keys, to ensure that the latest-greatest
467 // name cycle is read from file. Otherwise, they might come from memory.
468 auto key = dir->GetKey(HistoName.c_str());
469 if (key == nullptr) {
470 cxcoutEHF << "Histogram '" << HistoName
471 << "' wasn't found in file '" << InputFile
472 << "' in directory '" << HistoPath << "'." << std::endl;
473 throw hf_exc();
474 }
475
476 auto hist = key->ReadObject<TH1>();
477 if( !hist ) {
478 cxcoutEHF << "Histogram '" << HistoName
479 << "' wasn't found in file '" << InputFile
480 << "' in directory '" << HistoPath << "'." << std::endl;
481 throw hf_exc();
482 }
483
484
485 TH1 * ptr = (TH1 *) hist->Clone();
486
487 if(!ptr){
488 std::cerr << "Not all necessary info are set to access the input file. Check your config" << std::endl;
489 std::cerr << "filename: " << InputFile
490 << "path: " << HistoPath
491 << "obj: " << HistoName << std::endl;
492 throw hf_exc();
493 }
494
495 ptr->SetDirectory(nullptr);
496
497
498#ifdef DEBUG
499 std::cout << "Found Histogram: " << HistoName " at address: " << ptr
500 << " with integral " << ptr->Integral() << " and mean " << ptr->GetMean()
501 << std::endl;
502#endif
503
504 // Done
505 return ptr;
506
507}
#define cxcoutPHF
#define cxcoutDHF
#define cxcoutIHF
#define cxcoutWHF
#define cxcoutEHF
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
This class encapsulates all information for the statistical interpretation of one experiment.
Definition Channel.h:30
void Print(std::ostream &=std::cout)
Definition Channel.cxx:75
void SetData(const RooStats::HistFactory::Data &data)
set data object
Definition Channel.h:54
void AddSample(RooStats::HistFactory::Sample sample)
Definition Channel.cxx:67
TH1 * GetHistogram(std::string InputFile, std::string HistoPath, std::string HistoName, std::map< std::string, std::unique_ptr< TFile > > &lsof)
Open a file and copy a histogram.
Definition Channel.cxx:445
void SetStatErrorConfig(double RelErrorThreshold, Constraint::Type ConstraintType)
Definition Channel.cxx:199
void PrintXML(std::string const &directory, std::string const &prefix="") const
Definition Channel.cxx:105
Configuration for an *un*constrained, coherent shape variation of affected samples.
Configuration for a constrained, coherent shape variation of affected samples.
const std::string & GetHistoNameHigh() const
const std::string & GetHistoNameLow() const
const std::string & GetHistoPathLow() const
const std::string & GetInputFileHigh() const
const std::string & GetInputFileLow() const
const std::string & GetHistoPathHigh() const
std::string GetHistoName() const
get histogram name
Definition Sample.h:92
std::string GetName() const
get name of sample
Definition Sample.h:82
const TH1 * GetHisto() const
Definition Sample.cxx:88
void SetChannelName(const std::string &ChannelName)
set name of associated channel
Definition Sample.h:104
void SetHisto(TH1 *histo)
Definition Sample.h:45
std::string GetHistoPath() const
get histogram path
Definition Sample.h:97
RooStats::HistFactory::StatError & GetStatError()
Definition Sample.h:124
std::vector< RooStats::HistFactory::ShapeFactor > & GetShapeFactorList()
Definition Sample.h:113
std::vector< RooStats::HistFactory::HistoFactor > & GetHistoFactorList()
Definition Sample.h:111
std::string GetInputFile() const
get input ROOT file
Definition Sample.h:87
std::vector< RooStats::HistFactory::HistoSys > & GetHistoSysList()
Definition Sample.h:110
std::vector< RooStats::HistFactory::ShapeSys > & GetShapeSysList()
Definition Sample.h:112
*Un*constrained bin-by-bin variation of affected histogram.
const std::string & GetHistoPath() const
const std::string & GetInputFile() const
const std::string & GetHistoName() const
Constrained bin-by-bin variation of affected histogram.
std::string GetHistoPath() const
const TH1 * GetErrorHist() const
std::string GetHistoName() const
std::string GetInputFile() const
const std::string & GetHistoPath() const
const TH1 * GetErrorHist() const
const std::string & GetInputFile() const
const std::string & GetHistoName() const
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition TDirectory.h:221
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4075
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:577
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:8854
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7452
virtual Int_t GetNbinsX() const
Definition TH1.h:295
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7858
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9139
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5032
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2734
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
UInt_t GetDate(Bool_t inUTC=kTRUE, Int_t secOffset=0, UInt_t *year=nullptr, UInt_t *month=nullptr, UInt_t *day=nullptr) const
Return date in form of 19971224 (i.e.
Type GetType(const std::string &Name)
Namespace for the RooStats classes.
Definition Asimov.h:19