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.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() != "" ) {
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() != "" ) {
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 try {
334
335 if( fData.GetHisto() == nullptr && fData.GetInputFile() != "" ) {
336 cxcoutEHF << "Error: Data Histogram for channel " << GetName() << " is nullptr." << std::endl;
337 throw hf_exc();
338 }
339
340 // Get the histograms for the samples:
341 for( unsigned int sampItr = 0; sampItr < fSamples.size(); ++sampItr ) {
342
343 const RooStats::HistFactory::Sample& sample = fSamples.at( sampItr );
344
345 // Get the nominal histogram:
346 if( sample.GetHisto() == nullptr ) {
347 cxcoutEHF << "Error: Nominal Histogram for sample " << sample.GetName() << " is nullptr." << std::endl;
348 throw hf_exc();
349 }
350 else {
351
352 // Check if any bins are negative
353 std::vector<int> NegativeBinNumber;
354 std::vector<double> NegativeBinContent;
355 const TH1* histNominal = sample.GetHisto();
356 for(int ibin=1; ibin<=histNominal->GetNbinsX(); ++ibin) {
357 if(histNominal->GetBinContent(ibin) < 0) {
358 NegativeBinNumber.push_back(ibin);
359 NegativeBinContent.push_back(histNominal->GetBinContent(ibin));
360 }
361 }
362 if(NegativeBinNumber.size()>0) {
363 cxcoutWHF << "WARNING: Nominal Histogram " << histNominal->GetName() << " for Sample = " << sample.GetName()
364 << " in Channel = " << GetName() << " has negative entries in bin numbers = ";
365
366 for(unsigned int ibin=0; ibin<NegativeBinNumber.size(); ++ibin) {
367 if(ibin>0) std::cout << " , " ;
368 std::cout << NegativeBinNumber[ibin] << " : " << NegativeBinContent[ibin] ;
369 }
370 std::cout << std::endl;
371 }
372
373 }
374
375 // Get the StatError Histogram (if necessary)
376 if( sample.GetStatError().GetUseHisto() ) {
377 if( sample.GetStatError().GetErrorHist() == nullptr ) {
378 cxcoutEHF << "Error: Statistical Error Histogram for sample " << sample.GetName() << " is nullptr." << std::endl;
379 throw hf_exc();
380 }
381 }
382
383
384 // Get the HistoSys Variations:
385 for( unsigned int histoSysItr = 0; histoSysItr < sample.GetHistoSysList().size(); ++histoSysItr ) {
386
387 const RooStats::HistFactory::HistoSys& histoSys = sample.GetHistoSysList().at( histoSysItr );
388
389 if( histoSys.GetHistoLow() == nullptr ) {
390 cxcoutEHF << "Error: HistoSyst Low for Systematic " << histoSys.GetName()
391 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
392 throw hf_exc();
393 }
394 if( histoSys.GetHistoHigh() == nullptr ) {
395 cxcoutEHF << "Error: HistoSyst High for Systematic " << histoSys.GetName()
396 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
397 throw hf_exc();
398 }
399
400 } // End Loop over HistoSys
401
402
403 // Get the HistoFactor Variations:
404 for( unsigned int histoFactorItr = 0; histoFactorItr < sample.GetHistoFactorList().size(); ++histoFactorItr ) {
405
406 const RooStats::HistFactory::HistoFactor& histoFactor = sample.GetHistoFactorList().at( histoFactorItr );
407
408 if( histoFactor.GetHistoLow() == nullptr ) {
409 cxcoutEHF << "Error: HistoSyst Low for Systematic " << histoFactor.GetName()
410 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
411 throw hf_exc();
412 }
413 if( histoFactor.GetHistoHigh() == nullptr ) {
414 cxcoutEHF << "Error: HistoSyst High for Systematic " << histoFactor.GetName()
415 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
416 throw hf_exc();
417 }
418
419 } // End Loop over HistoFactor
420
421
422 // Get the ShapeSys Variations:
423 for( unsigned int shapeSysItr = 0; shapeSysItr < sample.GetShapeSysList().size(); ++shapeSysItr ) {
424
425 const RooStats::HistFactory::ShapeSys& shapeSys = sample.GetShapeSysList().at( shapeSysItr );
426
427 if( shapeSys.GetErrorHist() == nullptr ) {
428 cxcoutEHF << "Error: HistoSyst High for Systematic " << shapeSys.GetName()
429 << " in sample " << sample.GetName() << " is nullptr." << std::endl;
430 throw hf_exc();
431 }
432
433 } // End Loop over ShapeSys
434
435 } // End Loop over Samples
436
437 }
438 catch(std::exception& e)
439 {
440 std::cout << e.what() << std::endl;
441 return false;
442 }
443
444 return true;
445
446
447
448
449}
450
451
452
453/// Open a file and copy a histogram
454/// \param InputFile File where the histogram resides.
455/// \param HistoPath Path of the histogram in the file.
456/// \param HistoName Name of the histogram to retrieve.
457/// \param lsof List of open files. Helps to prevent opening and closing a file hundreds of times.
458TH1* RooStats::HistFactory::Channel::GetHistogram(std::string InputFile, std::string HistoPath, std::string HistoName, std::map<std::string,std::unique_ptr<TFile>>& lsof) {
459
460 cxcoutPHF << "Getting histogram " << InputFile << ":" << HistoPath << "/" << HistoName << std::endl;
461
462 auto& inFile = lsof[InputFile];
463 if (!inFile || !inFile->IsOpen()) {
464 inFile.reset( TFile::Open(InputFile.c_str()) );
465 if ( !inFile || !inFile->IsOpen() ) {
466 cxcoutEHF << "Error: Unable to open input file: " << InputFile << std::endl;
467 throw hf_exc();
468 }
469 cxcoutIHF << "Opened input file: " << InputFile << ": " << std::endl;
470 }
471
472 TDirectory* dir = inFile->GetDirectory(HistoPath.c_str());
473 if (dir == nullptr) {
474 cxcoutEHF << "Histogram path '" << HistoPath
475 << "' wasn't found in file '" << InputFile << "'." << std::endl;
476 throw hf_exc();
477 }
478
479 // Have to read histograms via keys, to ensure that the latest-greatest
480 // name cycle is read from file. Otherwise, they might come from memory.
481 auto key = dir->GetKey(HistoName.c_str());
482 if (key == nullptr) {
483 cxcoutEHF << "Histogram '" << HistoName
484 << "' wasn't found in file '" << InputFile
485 << "' in directory '" << HistoPath << "'." << std::endl;
486 throw hf_exc();
487 }
488
489 auto hist = dynamic_cast<TH1*>(key->ReadObj());
490 if( !hist ) {
491 cxcoutEHF << "Histogram '" << HistoName
492 << "' wasn't found in file '" << InputFile
493 << "' in directory '" << HistoPath << "'." << std::endl;
494 throw hf_exc();
495 }
496
497
498 TH1 * ptr = (TH1 *) hist->Clone();
499
500 if(!ptr){
501 std::cerr << "Not all necessary info are set to access the input file. Check your config" << std::endl;
502 std::cerr << "filename: " << InputFile
503 << "path: " << HistoPath
504 << "obj: " << HistoName << std::endl;
505 throw hf_exc();
506 }
507
508 ptr->SetDirectory(nullptr);
509
510
511#ifdef DEBUG
512 std::cout << "Found Histogram: " << HistoName " at address: " << ptr
513 << " with integral " << ptr->Integral() << " and mean " << ptr->GetMean()
514 << std::endl;
515#endif
516
517 // Done
518 return ptr;
519
520}
#define cxcoutPHF
#define cxcoutDHF
#define cxcoutIHF
#define cxcoutWHF
#define cxcoutEHF
#define e(i)
Definition RSha256.hxx:103
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:458
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:4053
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:8803
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:7445
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:7851
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:9088
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5025
TObject * Clone(const char *newname="") const override
Make a complete copy of the underlying object.
Definition TH1.cxx:2727
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