Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MakeModelAndMeasurementsFast.cxx
Go to the documentation of this file.
1// @(#)root/roostats:$Id: cranmer $
2// Author: Kyle Cranmer, Akira Shibata
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
12
13// from roofit
14#include "RooFit/ModelConfig.h"
15
16// from this package
19
20#include "HFMsgService.h"
21
22#include <TFile.h>
23#include <TSystem.h>
24
25#include <string>
26#include <vector>
27#include <map>
28#include <fstream>
29#include <sstream>
30
31/** ********************************************************************************************
32 \ingroup HistFactory
33
34 <p>
35 This is a package that creates a RooFit probability density function from ROOT histograms
36 of expected distributions and histograms that represent the +/- 1 sigma variations
37 from systematic effects. The resulting probability density function can then be used
38 with any of the statistical tools provided within RooStats, such as the profile
39 likelihood ratio, Feldman-Cousins, etc. In this version, the model is directly
40 fed to a likelihood ratio test, but it needs to be further factorized.</p>
41
42 <p>
43 The user needs to provide histograms (in picobarns per bin) and configure the job
44 with XML. The configuration XML is defined in the file `$ROOTSYS/config/HistFactorySchema.dtd`, but essentially
45 it is organized as follows (see the examples in `${ROOTSYS}/tutorials/histfactory/`)</p>
46
47 <ul>
48 <li> a top level 'Combination' that is composed of:</li>
49 <ul>
50 <li> several 'Channels' (eg. ee, emu, mumu), which are composed of:</li>
51 <ul>
52 <li> several 'Samples' (eg. signal, bkg1, bkg2, ...), each of which has:</li>
53 <ul>
54 <li> a name</li>
55 <li> if the sample is normalized by theory (eg N = L*sigma) or not (eg. data driven)</li>
56 <li> a nominal expectation histogram</li>
57 <li> a named 'Normalization Factor' (which can be fixed or allowed to float in a fit)</li>
58 <li> several 'Overall Systematics' in normalization with:</li>
59 <ul>
60 <li> a name</li>
61 <li> +/- 1 sigma variations (eg. 1.05 and 0.95 for a 5% uncertainty)</li>
62 </ul>
63 <li> several 'Histogram Systematics' in shape with:</li>
64 <ul>
65 <li> a name (which can be shared with the OverallSyst if correlated)</li>
66 <li> +/- 1 sigma variational histograms</li>
67 </ul>
68 </ul>
69 </ul>
70 <li> several 'Measurements' (corresponding to a full fit of the model) each of which specifies</li>
71 <ul>
72 <li> a name for this fit to be used in tables and files</li>
73 <li> what is the luminosity associated to the measurement in picobarns</li>
74 <li> which bins of the histogram should be used</li>
75 <li> what is the relative uncertainty on the luminosity </li>
76 <li> what is (are) the parameter(s) of interest that will be measured</li>
77 <li> which parameters should be fixed/floating (eg. nuisance parameters)</li>
78 </ul>
79 </ul>
80 </ul>
81*/
84 HistoToWorkspaceFactoryFast::Configuration const &cfg)
85{
86 std::unique_ptr<TFile> outFile;
87
88 auto& msgSvc = RooMsgService::instance();
89 msgSvc.getStream(1).removeTopic(RooFit::ObjectHandling);
90
91 cxcoutIHF << "Making Model and Measurements (Fast) for measurement: " << measurement.GetName() << std::endl;
92
93 double lumiError = measurement.GetLumi()*measurement.GetLumiRelErr();
94
95 cxcoutIHF << "using lumi = " << measurement.GetLumi() << " and lumiError = " << lumiError
96 << " including bins between " << measurement.GetBinLow() << " and " << measurement.GetBinHigh() << std::endl;
97
98 std::ostringstream parameterMessage;
99 parameterMessage << "fixing the following parameters:" << std::endl;
100
101 for (auto const &name : measurement.GetConstantParams()) {
102 parameterMessage << " " << name << '\n';
103 }
104 cxcoutIHF << parameterMessage.str();
105
106 std::string rowTitle = measurement.GetName();
107
108 std::vector<std::unique_ptr<RooWorkspace>> channel_workspaces;
109 std::vector<std::string> channel_names;
110
111 // Create the outFile - first check if the outputfile exists
112 std::string prefix = measurement.GetOutputFilePrefix();
113 // parse prefix to find output directory -
114 // assume there is a file prefix after the last "/" that we remove
115 // to get the directory name.
116 // We do by finding last occurrence of "/" and using as directory name what is before
117 // if we do not have a "/" in the prefix there is no output directory to be checked or created
118 size_t pos = prefix.rfind('/');
119 if (pos != std::string::npos) {
120 std::string outputDir = prefix.substr(0,pos);
121 cxcoutDHF << "Checking if output directory : " << outputDir << " - exists" << std::endl;
122 if (gSystem->OpenDirectory( outputDir.c_str() ) == nullptr ) {
123 cxcoutDHF << "Output directory : " << outputDir << " - does not exist, try to create" << std::endl;
124 int success = gSystem->MakeDirectory( outputDir.c_str() );
125 if( success != 0 ) {
126 std::string fullOutputDir = std::string(gSystem->pwd()) + std::string("/") + outputDir;
127 cxcoutEHF << "Error: Failed to make output directory: " << fullOutputDir << std::endl;
128 throw hf_exc();
129 }
130 }
131 }
132
133 // This holds the TGraphs that are created during the fit
134 std::string outputFileName = measurement.GetOutputFilePrefix() + "_" + measurement.GetName() + ".root";
135 cxcoutIHF << "Creating the output file: " << outputFileName << std::endl;
136 outFile = std::make_unique<TFile>(outputFileName.c_str(), "recreate");
137
138 cxcoutIHF << "Creating the HistoToWorkspaceFactoryFast factory" << std::endl;
139 HistoToWorkspaceFactoryFast factory{measurement, cfg};
140
141 // Make the factory, and do some preprocessing
142 // HistoToWorkspaceFactoryFast factory(measurement, rowTitle, outFile);
143 cxcoutIHF << "Setting preprocess functions" << std::endl;
144 factory.SetFunctionsToPreprocess( measurement.GetPreprocessFunctions() );
145
146 // First: Loop to make the individual channels
147 for( unsigned int chanItr = 0; chanItr < measurement.GetChannels().size(); ++chanItr ) {
148
149 HistFactory::Channel& channel = measurement.GetChannels().at( chanItr );
150 if( ! channel.CheckHistograms() ) {
151 cxcoutEHF << "MakeModelAndMeasurementsFast: Channel: " << channel.GetName()
152 << " has uninitialized histogram pointers" << std::endl;
153 throw hf_exc();
154 }
155
156 // Make the workspace for this individual channel
157 std::string ch_name = channel.GetName();
158 cxcoutPHF << "Starting to process channel: " << ch_name << std::endl;
159 channel_names.push_back(ch_name);
160 std::unique_ptr<RooWorkspace> ws_single{factory.MakeSingleChannelModel( measurement, channel )};
161
162 if (cfg.createPerRegionWorkspaces) {
163 // Make the output
164 std::string ChannelFileName = measurement.GetOutputFilePrefix() + "_"
165 + ch_name + "_" + rowTitle + "_model.root";
166 cxcoutIHF << "Opening File to hold channel: " << ChannelFileName << std::endl;
167 std::unique_ptr<TFile> chanFile{TFile::Open( ChannelFileName.c_str(), "RECREATE" )};
168 chanFile->WriteTObject(ws_single.get());
169 // Now, write the measurement to the file
170 // Make a new measurement for only this channel
171 RooStats::HistFactory::Measurement meas_chan( measurement );
172 meas_chan.GetChannels().clear();
173 meas_chan.GetChannels().push_back( channel );
174 cxcoutIHF << "About to write channel measurement to file" << std::endl;
175 meas_chan.writeToFile( chanFile.get() );
176 cxcoutPHF << "Successfully wrote channel to file" << std::endl;
177 }
178
179 channel_workspaces.emplace_back(std::move(ws_single));
180 } // End loop over channels
181
182 /***
183 Second: Make the combined model:
184 If you want output histograms in root format, create and pass it to the combine routine.
185 "combine" : will do the individual cross-section measurements plus combination
186 ***/
187
188 // Use HistFactory to combine the individual channel workspaces
189 std::unique_ptr<RooWorkspace> ws{factory.MakeCombinedModel(channel_names, channel_workspaces)};
190
191 // Configure that workspace
192 HistoToWorkspaceFactoryFast::ConfigureWorkspaceForMeasurement("simPdf", ws.get(), measurement);
193
194 {
195 std::string CombinedFileName = measurement.GetOutputFilePrefix() + "_combined_"
196 + rowTitle + "_model.root";
197 cxcoutPHF << "Writing combined workspace to file: " << CombinedFileName << std::endl;
198 std::unique_ptr<TFile> combFile{TFile::Open( CombinedFileName.c_str(), "RECREATE" )};
199 if( combFile == nullptr ) {
200 cxcoutEHF << "Error: Failed to open file " << CombinedFileName << std::endl;
201 throw hf_exc();
202 }
203 combFile->WriteTObject(ws.get());
204 cxcoutPHF << "Writing combined measurement to file: " << CombinedFileName << std::endl;
205 measurement.writeToFile( combFile.get() );
206 }
207
208 msgSvc.getStream(1).addTopic(RooFit::ObjectHandling);
209
210 return RooFit::makeOwningPtr(std::move(ws));
211}
#define cxcoutPHF
#define cxcoutDHF
#define cxcoutIHF
#define cxcoutEHF
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
char name[80]
Definition TGX11.cxx:110
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
static RooMsgService & instance()
Return reference to singleton instance.
The RooStats::HistFactory::Measurement class can be used to construct a model by combining multiple R...
Definition Measurement.h:31
void writeToFile(TFile *file)
A measurement, once fully configured, can be saved into a ROOT file.
double GetLumiRelErr()
retrieve relative uncertainty on luminosity
Definition Measurement.h:91
std::vector< RooStats::HistFactory::Channel > & GetChannels()
std::string GetOutputFilePrefix()
retrieve prefix for output files
Definition Measurement.h:42
std::vector< std::string > GetPreprocessFunctions() const
Returns a list of defined preprocess function expressions.
double GetLumi()
retrieve integrated luminosity
Definition Measurement.h:89
Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *option="", Int_t bufsize=0) override
Write object obj to this directory.
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:4086
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * pwd()
Definition TSystem.h:424
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition TSystem.cxx:836
virtual int MakeDirectory(const char *name)
Make a directory.
Definition TSystem.cxx:827
@ ObjectHandling
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:40
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:35
RooFit::OwningPtr< RooWorkspace > MakeModelAndMeasurementFast(RooStats::HistFactory::Measurement &measurement, HistoToWorkspaceFactoryFast::Configuration const &cfg={})