Logo ROOT  
Reference Guide
 
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 <stdlib.h>
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.size() != 0 ) {
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 directory, std::string prefix ) {
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 != "" ) 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 /*
138 xml << " <Data HistoName=\"" << fData.GetHistoName() << "\" "
139 << "InputFile=\"" << fData.GetInputFile() << "\" "
140 << "HistoPath=\"" << fData.GetHistoPath() << "\" "
141 << " /> " << std::endl << std::endl;
142 */
143
144 fStatErrorConfig.PrintXML( xml );
145 /*
146 xml << " <StatErrorConfig RelErrorThreshold=\"" << fStatErrorConfig.GetRelErrorThreshold() << "\" "
147 << "ConstraintType=\"" << Constraint::Name( fStatErrorConfig.GetConstraintType() ) << "\" "
148 << "/> " << std::endl << std::endl;
149 */
150
151 for( unsigned int i = 0; i < fSamples.size(); ++i ) {
152 fSamples.at(i).PrintXML( xml );
153 xml << std::endl << std::endl;
154 }
155
156 xml << std::endl;
157 xml << " </Channel> " << std::endl;
158 xml.close();
159
160 cxcoutPHF << "Finished printing XML files" << std::endl;
161
162}
163
164
165void RooStats::HistFactory::Channel::SetData( std::string DataHistoName, std::string DataInputFile, std::string DataHistoPath ) {
166 // set data for this channel by specifying the name of the histogram,
167 // the external ROOT file and the path to the histogram inside the ROOT file
168
169 fData.SetHistoName( DataHistoName );
170 fData.SetInputFile( DataInputFile );
171 fData.SetHistoPath( DataHistoPath );
172
173}
174
175
176
178 // set data directly to some histogram
179 fData.SetHisto( hData );
180}
181
183
184 // For a NumberCounting measurement only
185 // Set the value of data in a particular channel
186 //
187 // Internally, this simply creates a 1-bin TH1F for you
188
189 std::string DataHistName = fName + "_data";
190
191 // Histogram has 1-bin (hard-coded)
192 TH1F* hData = new TH1F( DataHistName.c_str(), DataHistName.c_str(), 1, 0, 1 );
193 hData->SetBinContent( 1, val );
194
195 // Set the histogram of the internally held data
196 // node of this channel to this newly created histogram
197 SetData( hData );
198
199}
200
201
202void RooStats::HistFactory::Channel::SetStatErrorConfig( double StatRelErrorThreshold, Constraint::Type StatConstraintType ) {
203
204 fStatErrorConfig.SetRelErrorThreshold( StatRelErrorThreshold );
205 fStatErrorConfig.SetConstraintType( StatConstraintType );
206
207}
208
209void RooStats::HistFactory::Channel::SetStatErrorConfig( double StatRelErrorThreshold, std::string StatConstraintType ) {
210
211 fStatErrorConfig.SetRelErrorThreshold( StatRelErrorThreshold );
212 fStatErrorConfig.SetConstraintType( Constraint::GetType(StatConstraintType) );
213
214}
215
216
217
219
220 // Loop through all Samples and Systematics
221 // and collect all necessary histograms
222
223 // Handles to open files for collecting histograms
224 std::map<std::string,std::unique_ptr<TFile>> fileHandles;
225
226 // Get the Data Histogram:
227
228 if( fData.GetInputFile() != "" ) {
229 fData.SetHisto( GetHistogram(fData.GetInputFile(),
230 fData.GetHistoPath(),
231 fData.GetHistoName(),
232 fileHandles) );
233 }
234
235 // Collect any histograms for additional Datasets
236 for( unsigned int i=0; i < fAdditionalData.size(); ++i) {
237 RooStats::HistFactory::Data& data = fAdditionalData.at(i);
238 if( data.GetInputFile() != "" ) {
239 data.SetHisto( GetHistogram(data.GetInputFile(), data.GetHistoPath(), data.GetHistoName(), fileHandles) );
240 }
241 }
242
243 // Get the histograms for the samples:
244 for( unsigned int sampItr = 0; sampItr < fSamples.size(); ++sampItr ) {
245
246 RooStats::HistFactory::Sample& sample = fSamples.at( sampItr );
247
248
249 // Get the nominal histogram:
250 cxcoutDHF << "Collecting Nominal Histogram" << std::endl;
251 TH1* Nominal = GetHistogram(sample.GetInputFile(),
252 sample.GetHistoPath(),
253 sample.GetHistoName(),
254 fileHandles);
255
256 sample.SetHisto( Nominal );
257
258
259 // Get the StatError Histogram (if necessary)
260 if( sample.GetStatError().GetUseHisto() ) {
261 sample.GetStatError().SetErrorHist( GetHistogram(sample.GetStatError().GetInputFile(),
262 sample.GetStatError().GetHistoPath(),
263 sample.GetStatError().GetHistoName(),
264 fileHandles) );
265 }
266
267
268 // Get the HistoSys Variations:
269 for( unsigned int histoSysItr = 0; histoSysItr < sample.GetHistoSysList().size(); ++histoSysItr ) {
270
271 RooStats::HistFactory::HistoSys& histoSys = sample.GetHistoSysList().at( histoSysItr );
272
273 histoSys.SetHistoLow( GetHistogram(histoSys.GetInputFileLow(),
274 histoSys.GetHistoPathLow(),
275 histoSys.GetHistoNameLow(),
276 fileHandles) );
277
278 histoSys.SetHistoHigh( GetHistogram(histoSys.GetInputFileHigh(),
279 histoSys.GetHistoPathHigh(),
280 histoSys.GetHistoNameHigh(),
281 fileHandles) );
282 } // End Loop over HistoSys
283
284
285 // Get the HistoFactor Variations:
286 for( unsigned int histoFactorItr = 0; histoFactorItr < sample.GetHistoFactorList().size(); ++histoFactorItr ) {
287
288 RooStats::HistFactory::HistoFactor& histoFactor = sample.GetHistoFactorList().at( histoFactorItr );
289
290 histoFactor.SetHistoLow( GetHistogram(histoFactor.GetInputFileLow(),
291 histoFactor.GetHistoPathLow(),
292 histoFactor.GetHistoNameLow(),
293 fileHandles) );
294
295 histoFactor.SetHistoHigh( GetHistogram(histoFactor.GetInputFileHigh(),
296 histoFactor.GetHistoPathHigh(),
297 histoFactor.GetHistoNameHigh(),
298 fileHandles) );
299 } // End Loop over HistoFactor
300
301
302 // Get the ShapeSys Variations:
303 for( unsigned int shapeSysItr = 0; shapeSysItr < sample.GetShapeSysList().size(); ++shapeSysItr ) {
304
305 RooStats::HistFactory::ShapeSys& shapeSys = sample.GetShapeSysList().at( shapeSysItr );
306
307 shapeSys.SetErrorHist( GetHistogram(shapeSys.GetInputFile(),
308 shapeSys.GetHistoPath(),
309 shapeSys.GetHistoName(),
310 fileHandles) );
311 } // End Loop over ShapeSys
312
313
314 // Get any initial shape for a ShapeFactor
315 for( unsigned int shapeFactorItr = 0; shapeFactorItr < sample.GetShapeFactorList().size(); ++shapeFactorItr ) {
316
317 RooStats::HistFactory::ShapeFactor& shapeFactor = sample.GetShapeFactorList().at( shapeFactorItr );
318
319 // Check if we need an InitialShape
320 if( shapeFactor.HasInitialShape() ) {
321 TH1* hist = GetHistogram( shapeFactor.GetInputFile(), shapeFactor.GetHistoPath(),
322 shapeFactor.GetHistoName(), fileHandles );
323 shapeFactor.SetInitialShape( hist );
324 }
325
326 } // End Loop over ShapeFactor
327
328 } // End Loop over Samples
329}
330
331
333
334 // Check that all internal histogram pointers
335 // are properly configured (ie that they're not NULL)
336
337 try {
338
339 if( fData.GetHisto() == NULL && fData.GetInputFile() != "" ) {
340 cxcoutEHF << "Error: Data Histogram for channel " << GetName() << " is NULL." << std::endl;
341 throw hf_exc();
342 }
343
344 // Get the histograms for the samples:
345 for( unsigned int sampItr = 0; sampItr < fSamples.size(); ++sampItr ) {
346
347 const RooStats::HistFactory::Sample& sample = fSamples.at( sampItr );
348
349 // Get the nominal histogram:
350 if( sample.GetHisto() == NULL ) {
351 cxcoutEHF << "Error: Nominal Histogram for sample " << sample.GetName() << " is NULL." << std::endl;
352 throw hf_exc();
353 }
354 else {
355
356 // Check if any bins are negative
357 std::vector<int> NegativeBinNumber;
358 std::vector<double> NegativeBinContent;
359 const TH1* histNominal = sample.GetHisto();
360 for(int ibin=1; ibin<=histNominal->GetNbinsX(); ++ibin) {
361 if(histNominal->GetBinContent(ibin) < 0) {
362 NegativeBinNumber.push_back(ibin);
363 NegativeBinContent.push_back(histNominal->GetBinContent(ibin));
364 }
365 }
366 if(NegativeBinNumber.size()>0) {
367 cxcoutWHF << "WARNING: Nominal Histogram " << histNominal->GetName() << " for Sample = " << sample.GetName()
368 << " in Channel = " << GetName() << " has negative entries in bin numbers = ";
369
370 for(unsigned int ibin=0; ibin<NegativeBinNumber.size(); ++ibin) {
371 if(ibin>0) std::cout << " , " ;
372 std::cout << NegativeBinNumber[ibin] << " : " << NegativeBinContent[ibin] ;
373 }
374 std::cout << std::endl;
375 }
376
377 }
378
379 // Get the StatError Histogram (if necessary)
380 if( sample.GetStatError().GetUseHisto() ) {
381 if( sample.GetStatError().GetErrorHist() == NULL ) {
382 cxcoutEHF << "Error: Statistical Error Histogram for sample " << sample.GetName() << " is NULL." << std::endl;
383 throw hf_exc();
384 }
385 }
386
387
388 // Get the HistoSys Variations:
389 for( unsigned int histoSysItr = 0; histoSysItr < sample.GetHistoSysList().size(); ++histoSysItr ) {
390
391 const RooStats::HistFactory::HistoSys& histoSys = sample.GetHistoSysList().at( histoSysItr );
392
393 if( histoSys.GetHistoLow() == NULL ) {
394 cxcoutEHF << "Error: HistoSyst Low for Systematic " << histoSys.GetName()
395 << " in sample " << sample.GetName() << " is NULL." << std::endl;
396 throw hf_exc();
397 }
398 if( histoSys.GetHistoHigh() == NULL ) {
399 cxcoutEHF << "Error: HistoSyst High for Systematic " << histoSys.GetName()
400 << " in sample " << sample.GetName() << " is NULL." << std::endl;
401 throw hf_exc();
402 }
403
404 } // End Loop over HistoSys
405
406
407 // Get the HistoFactor Variations:
408 for( unsigned int histoFactorItr = 0; histoFactorItr < sample.GetHistoFactorList().size(); ++histoFactorItr ) {
409
410 const RooStats::HistFactory::HistoFactor& histoFactor = sample.GetHistoFactorList().at( histoFactorItr );
411
412 if( histoFactor.GetHistoLow() == NULL ) {
413 cxcoutEHF << "Error: HistoSyst Low for Systematic " << histoFactor.GetName()
414 << " in sample " << sample.GetName() << " is NULL." << std::endl;
415 throw hf_exc();
416 }
417 if( histoFactor.GetHistoHigh() == NULL ) {
418 cxcoutEHF << "Error: HistoSyst High for Systematic " << histoFactor.GetName()
419 << " in sample " << sample.GetName() << " is NULL." << std::endl;
420 throw hf_exc();
421 }
422
423 } // End Loop over HistoFactor
424
425
426 // Get the ShapeSys Variations:
427 for( unsigned int shapeSysItr = 0; shapeSysItr < sample.GetShapeSysList().size(); ++shapeSysItr ) {
428
429 const RooStats::HistFactory::ShapeSys& shapeSys = sample.GetShapeSysList().at( shapeSysItr );
430
431 if( shapeSys.GetErrorHist() == NULL ) {
432 cxcoutEHF << "Error: HistoSyst High for Systematic " << shapeSys.GetName()
433 << " in sample " << sample.GetName() << " is NULL." << std::endl;
434 throw hf_exc();
435 }
436
437 } // End Loop over ShapeSys
438
439 } // End Loop over Samples
440
441 }
442 catch(std::exception& e)
443 {
444 std::cout << e.what() << std::endl;
445 return false;
446 }
447
448 return true;
449
450
451
452
453}
454
455
456
457/// Open a file and copy a histogram
458/// \param InputFile File where the histogram resides.
459/// \param HistoPath Path of the histogram in the file.
460/// \param HistoName Name of the histogram to retrieve.
461/// \param lsof List of open files. Helps to prevent opening and closing a file hundreds of times.
462TH1* RooStats::HistFactory::Channel::GetHistogram(std::string InputFile, std::string HistoPath, std::string HistoName, std::map<std::string,std::unique_ptr<TFile>>& lsof) {
463
464 cxcoutPHF << "Getting histogram " << InputFile << ":" << HistoPath << "/" << HistoName << std::endl;
465
466 auto& inFile = lsof[InputFile];
467 if (!inFile || !inFile->IsOpen()) {
468 inFile.reset( TFile::Open(InputFile.c_str()) );
469 if ( !inFile || !inFile->IsOpen() ) {
470 cxcoutEHF << "Error: Unable to open input file: " << InputFile << std::endl;
471 throw hf_exc();
472 }
473 cxcoutIHF << "Opened input file: " << InputFile << ": " << std::endl;
474 }
475
476 TDirectory* dir = inFile->GetDirectory(HistoPath.c_str());
477 if (dir == nullptr) {
478 cxcoutEHF << "Histogram path '" << HistoPath
479 << "' wasn't found in file '" << InputFile << "'." << std::endl;
480 throw hf_exc();
481 }
482
483 // Have to read histograms via keys, to ensure that the latest-greatest
484 // name cycle is read from file. Otherwise, they might come from memory.
485 auto key = dir->GetKey(HistoName.c_str());
486 if (key == nullptr) {
487 cxcoutEHF << "Histogram '" << HistoName
488 << "' wasn't found in file '" << InputFile
489 << "' in directory '" << HistoPath << "'." << std::endl;
490 throw hf_exc();
491 }
492
493 auto hist = dynamic_cast<TH1*>(key->ReadObj());
494 if( !hist ) {
495 cxcoutEHF << "Histogram '" << HistoName
496 << "' wasn't found in file '" << InputFile
497 << "' in directory '" << HistoPath << "'." << std::endl;
498 throw hf_exc();
499 }
500
501
502 TH1 * ptr = (TH1 *) hist->Clone();
503
504 if(!ptr){
505 std::cerr << "Not all necessary info are set to access the input file. Check your config" << std::endl;
506 std::cerr << "filename: " << InputFile
507 << "path: " << HistoPath
508 << "obj: " << HistoName << std::endl;
509 throw hf_exc();
510 }
511
512 ptr->SetDirectory(nullptr);
513
514
515#ifdef DEBUG
516 std::cout << "Found Histogram: " << HistoName " at address: " << ptr
517 << " with integral " << ptr->Integral() << " and mean " << ptr->GetMean()
518 << std::endl;
519#endif
520
521 // Done
522 return ptr;
523
524}
#define cxcoutPHF
#define cxcoutDHF
#define cxcoutIHF
#define cxcoutWHF
#define cxcoutEHF
#define e(i)
Definition RSha256.hxx:103
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 PrintXML(std::string Directory, std::string Prefix="")
Definition Channel.cxx:105
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:462
void SetStatErrorConfig(double RelErrorThreshold, Constraint::Type ConstraintType)
Definition Channel.cxx:202
std::string GetHistoPath() const
Definition Data.h:43
void SetHisto(TH1 *Hist)
Definition Data.h:51
std::string GetInputFile() const
Definition Data.h:37
std::string GetHistoName() const
Definition Data.h:40
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:93
std::string GetName() const
get name of sample
Definition Sample.h:83
const TH1 * GetHisto() const
Definition Sample.cxx:99
void SetChannelName(const std::string &ChannelName)
set name of associated channel
Definition Sample.h:105
void SetHisto(TH1 *histo)
Definition Sample.h:46
std::string GetHistoPath() const
get histogram path
Definition Sample.h:98
RooStats::HistFactory::StatError & GetStatError()
Definition Sample.h:125
std::vector< RooStats::HistFactory::ShapeFactor > & GetShapeFactorList()
Definition Sample.h:114
std::vector< RooStats::HistFactory::HistoFactor > & GetHistoFactorList()
Definition Sample.h:112
std::string GetInputFile() const
get input ROOT file
Definition Sample.h:88
std::vector< RooStats::HistFactory::HistoSys > & GetHistoSysList()
Definition Sample.h:111
std::vector< RooStats::HistFactory::ShapeSys > & GetShapeSysList()
Definition Sample.h:113
*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:175
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:3997
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:575
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:8777
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:7428
TObject * Clone(const char *newname=0) const
Make a complete copy of the underlying object.
Definition TH1.cxx:2740
virtual Int_t GetNbinsX() const
Definition TH1.h:296
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7834
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:9062
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:4993
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:71
UInt_t GetDate(Bool_t inUTC=kTRUE, Int_t secOffset=0, UInt_t *year=0, UInt_t *month=0, UInt_t *day=0) const
Return date in form of 19971224 (i.e.
Type GetType(const std::string &Name)
Namespace for the RooStats classes.
Definition Asimov.h:19