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 <sstream>
26#include <string>
27#include <vector>
28
29/** ********************************************************************************************
30 \ingroup HistFactory
31
32 <p>
33 This is a package that creates a RooFit probability density function from ROOT histograms
34 of expected distributions and histograms that represent the +/- 1 sigma variations
35 from systematic effects. The resulting probability density function can then be used
36 with any of the statistical tools provided within RooStats, such as the profile
37 likelihood ratio, Feldman-Cousins, etc. In this version, the model is directly
38 fed to a likelihood ratio test, but it needs to be further factorized.</p>
39
40 <p>
41 The user needs to provide histograms (in picobarns per bin) and configure the job
42 with XML. The configuration XML is defined in the file `$ROOTSYS/config/HistFactorySchema.dtd`, but essentially
43 it is organized as follows (see the examples in `${ROOTSYS}/tutorials/roofit/histfactory/`)</p>
44
45 <ul>
46 <li> a top level 'Combination' that is composed of:</li>
47 <ul>
48 <li> several 'Channels' (eg. ee, emu, mumu), which are composed of:</li>
49 <ul>
50 <li> several 'Samples' (eg. signal, bkg1, bkg2, ...), each of which has:</li>
51 <ul>
52 <li> a name</li>
53 <li> if the sample is normalized by theory (eg N = L*sigma) or not (eg. data driven)</li>
54 <li> a nominal expectation histogram</li>
55 <li> a named 'Normalization Factor' (which can be fixed or allowed to float in a fit)</li>
56 <li> several 'Overall Systematics' in normalization with:</li>
57 <ul>
58 <li> a name</li>
59 <li> +/- 1 sigma variations (eg. 1.05 and 0.95 for a 5% uncertainty)</li>
60 </ul>
61 <li> several 'Histogram Systematics' in shape with:</li>
62 <ul>
63 <li> a name (which can be shared with the OverallSyst if correlated)</li>
64 <li> +/- 1 sigma variational histograms</li>
65 </ul>
66 </ul>
67 </ul>
68 <li> several 'Measurements' (corresponding to a full fit of the model) each of which specifies</li>
69 <ul>
70 <li> a name for this fit to be used in tables and files</li>
71 <li> what is the luminosity associated to the measurement in picobarns</li>
72 <li> which bins of the histogram should be used</li>
73 <li> what is the relative uncertainty on the luminosity </li>
74 <li> what is (are) the parameter(s) of interest that will be measured</li>
75 <li> which parameters should be fixed/floating (eg. nuisance parameters)</li>
76 </ul>
77 </ul>
78 </ul>
79*/
80
81
82/// \brief Creates a statistical model and associated RooFit workspace(s) from a
83/// HistFactory measurement configuration.
84///
85/// This function processes a RooStats::HistFactory::Measurement using the fast
86/// RooStats::HistFactory::HistoToWorkspaceFactoryFast machinery. It creates
87/// individual channel workspaces, optionally writes them to disk, and then
88/// combines them into a single RooWorkspace representing the full statistical
89/// model.
90///
91/// \param measurement Object containing the configuration of the statistical
92/// analysis, including luminosity, binning, systematic
93/// uncertainties, and channels.
94/// \param cfg Configuration object that controls behavior such as workspace
95/// file creation.
96///
97/// \return The combined `RooWorkspace`, or `nullptr` if workspace creation fails.
98
101 HistoToWorkspaceFactoryFast::Configuration const &cfg)
102{
103 // Make sure that topic is added back on function return.
104 struct RemoveTopicRAII {
105 RemoveTopicRAII() { RooMsgService::instance().getStream(1).removeTopic(RooFit::ObjectHandling); }
108
109 cxcoutIHF << "Making Model and Measurements (Fast) for measurement: " << measurement.GetName() << std::endl;
110
111 double lumiError = measurement.GetLumi()*measurement.GetLumiRelErr();
112
113 cxcoutIHF << "using lumi = " << measurement.GetLumi() << " and lumiError = " << lumiError
114 << " including bins between " << measurement.GetBinLow() << " and " << measurement.GetBinHigh() << std::endl;
115
116 std::ostringstream parameterMessage;
117 parameterMessage << "fixing the following parameters:" << std::endl;
118
119 for (auto const &name : measurement.GetConstantParams()) {
120 parameterMessage << " " << name << '\n';
121 }
123
124 std::string rowTitle = measurement.GetName();
125
126 std::vector<std::unique_ptr<RooWorkspace>> channel_workspaces;
127 std::vector<std::string> channel_names;
128
129 auto createOutputDirectory = [](std::string const &prefix) {
130 // Parse prefix to find output directory - assume there is a file prefix
131 // after the last "/" that we remove to get the directory name. We do by
132 // finding last occurrence of "/" and using as directory name what is
133 // before if we do not have a "/" in the prefix there is no output
134 // directory to be checked or created.
135 size_t pos = prefix.rfind('/');
136 if (pos == std::string::npos) {
137 return;
138 }
139 std::string outputDir = prefix.substr(0,pos);
140 cxcoutDHF << "Checking if output directory : " << outputDir << " - exists" << std::endl;
141 void *outdir = gSystem->OpenDirectory( outputDir.c_str() );
142 if (outdir) {
144 return;
145 }
146 cxcoutDHF << "Output directory : " << outputDir << " - does not exist, try to create" << std::endl;
147 int success = gSystem->MakeDirectory( outputDir.c_str() );
148 if( success != 0 ) {
149 std::string fullOutputDir = gSystem->pwd() + std::string("/") + outputDir;
150 cxcoutEHF << "Error: Failed to make output directory: " << fullOutputDir << std::endl;
151 throw hf_exc();
152 }
153 };
154
155 // Make the factory, and do some preprocessing
156 cxcoutIHF << "Creating the HistoToWorkspaceFactoryFast factory" << std::endl;
157 HistoToWorkspaceFactoryFast factory{measurement, cfg};
158
159 cxcoutIHF << "Setting preprocess functions" << std::endl;
160 factory.SetFunctionsToPreprocess( measurement.GetPreprocessFunctions() );
161
162 // First: Loop to make the individual channels
163 for( unsigned int chanItr = 0; chanItr < measurement.GetChannels().size(); ++chanItr ) {
164
165 HistFactory::Channel& channel = measurement.GetChannels().at( chanItr );
166 if( ! channel.CheckHistograms() ) {
167 cxcoutEHF << "MakeModelAndMeasurementsFast: Channel: " << channel.GetName()
168 << " has uninitialized histogram pointers" << std::endl;
169 throw hf_exc();
170 }
171
172 // Make the workspace for this individual channel
173 std::string ch_name = channel.GetName();
174 cxcoutPHF << "Starting to process channel: " << ch_name << std::endl;
175 channel_names.push_back(ch_name);
176 std::unique_ptr<RooWorkspace> ws_single{factory.MakeSingleChannelModel( measurement, channel )};
177
178 if (cfg.createPerRegionWorkspaces) {
179 std::string prefix = measurement.GetOutputFilePrefix();
180 createOutputDirectory(prefix);
181 // Make the output
182 std::string ChannelFileName = prefix + "_"
183 + ch_name + "_" + rowTitle + "_model.root";
184 cxcoutIHF << "Opening File to hold channel: " << ChannelFileName << std::endl;
185 std::unique_ptr<TFile> chanFile{TFile::Open( ChannelFileName.c_str(), "RECREATE" )};
186 chanFile->WriteTObject(ws_single.get());
187 // Now, write the measurement to the file
188 // Make a new measurement for only this channel
190 meas_chan.GetChannels().clear();
191 meas_chan.GetChannels().push_back( channel );
192 cxcoutIHF << "About to write channel measurement to file" << std::endl;
193 meas_chan.writeToFile( chanFile.get() );
194 cxcoutPHF << "Successfully wrote channel to file" << std::endl;
195 }
196
197 channel_workspaces.emplace_back(std::move(ws_single));
198 } // End loop over channels
199
200 /***
201 Second: Make the combined model:
202 If you want output histograms in root format, create and pass it to the combine routine.
203 "combine" : will do the individual cross-section measurements plus combination
204 ***/
205
206 // Use HistFactory to combine the individual channel workspaces
207 std::unique_ptr<RooWorkspace> ws{factory.MakeCombinedModel(channel_names, channel_workspaces)};
208
209 // Configure that workspace
210 HistoToWorkspaceFactoryFast::ConfigureWorkspaceForMeasurement("simPdf", ws.get(), measurement);
211
212 if (cfg.createWorkspaceFile) {
213 std::string prefix = measurement.GetOutputFilePrefix();
214 createOutputDirectory(prefix);
215 std::string CombinedFileName = prefix + "_combined_"
216 + rowTitle + "_model.root";
217 cxcoutPHF << "Writing combined workspace to file: " << CombinedFileName << std::endl;
218 std::unique_ptr<TFile> combFile{TFile::Open( CombinedFileName.c_str(), "RECREATE" )};
219 if( combFile == nullptr ) {
220 cxcoutEHF << "Error: Failed to open file " << CombinedFileName << std::endl;
221 throw hf_exc();
222 }
223 combFile->WriteTObject(ws.get());
224 cxcoutPHF << "Writing combined measurement to file: " << CombinedFileName << std::endl;
225 measurement.writeToFile( combFile.get() );
226 }
227
228 return RooFit::makeOwningPtr(std::move(ws));
229}
#define cxcoutPHF
#define cxcoutDHF
#define cxcoutIHF
#define cxcoutEHF
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:110
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
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
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:4131
const char * pwd()
Definition TSystem.h:434
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:857
virtual void * OpenDirectory(const char *name)
Open a directory.
Definition TSystem.cxx:848
virtual int MakeDirectory(const char *name)
Make a directory.
Definition TSystem.cxx:838
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
@ 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
RooFit::OwningPtr< RooWorkspace > MakeModelAndMeasurementFast(RooStats::HistFactory::Measurement &measurement, HistoToWorkspaceFactoryFast::Configuration const &cfg={})