ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/algomez/Stops/BATLimits/cls.cc
Revision: 1.1
Committed: Thu Sep 5 03:58:16 2013 UTC (11 years, 8 months ago) by algomez
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Log Message:
First version

File Contents

# User Rev Content
1 algomez 1.1 #include <iostream>
2     #include <cmath>
3     #include <cassert>
4     #include <sstream>
5    
6     #include <TGraph.h>
7     #include <TFile.h>
8     #include <TH1D.h>
9     #include <TCanvas.h>
10     #include <TF1.h>
11     #include <TMath.h>
12     #include <TROOT.h>
13    
14     #include "binneddata.hh"
15     #include "fit.hh"
16     #include "statistics.hh"
17    
18     ////////////////////////////////////////////////////////////////////////////////
19     // magic numbers
20     ////////////////////////////////////////////////////////////////////////////////
21    
22     // number of pseudoexperiments
23     const int NPES=0;
24    
25     // number of samples of nuisance parameters for Bayesian MC integration
26     const int NSAMPLES=2E5;
27    
28     // alpha (1-alpha=confidence interval)
29     const double ALPHA=0.05;
30    
31     // left side tail
32     const double LEFTSIDETAIL=0.0;
33    
34     // output file name
35     const char* OUTPUTFILE="stats.root";
36    
37     // input file name
38     const char* INPUTFILE="dijet_mass_HT_fat_1p010fbm1.txt";
39    
40     // histogram binning
41     const int NBINS=34;
42     double BOUNDARIES[NBINS] = { 838,
43     890, 944, 1000, 1058, 1118, 1181, 1246, 1313, 1383,
44     1455, 1530, 1607, 1687, 1770, 1856, 1945, 2037, 2132,
45     2231, 2332, 2438, 2546, 2659, 2775, 2895, 3019, 3147,
46     3275, 3403, 3531, 3659, 3787, 3915 };
47    
48     // parameters
49     double SIGMASS=0;
50     const int NPARS=8;
51     const int POIINDEX=0; // which parameter is "of interest"
52     const char* PAR_NAMES[8] = { "xs", "lumi", "jes", "jer", "bkg norm", "p1", "p2", "p3" };
53     const double PAR_GUESSES[8] = { 0.1, 1010., 1.0, 1.0, 5.6E-2, 7.4, 6.3, 0.2 };
54     const double PAR_MIN[8] = { 0.0, 0.0, 0.0, 0.0, 0., 0.0, 0.0, 0.0 };
55     const double PAR_MAX[8] = { 1.E6, 5000., 2.0, 2.0, 10.0, 100.0, 100.0, 10.0 };
56     const double PAR_ERR[8] = { 0.01, 40.4, 0.04, 0.10, 1.E-3, 1.0, 1.0, 0.1 };
57     const int PAR_TYPE[8] = { 1, 1, 1, 1, 0, 0, 0, 0 }; // 1 = signal, 0 = background
58     const int PAR_NUIS[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; // 1 = nuisance parameter, 0 = not varied (the POI is not a nuisance parameter)
59    
60     TH1D* HIST=0; // signal histogram
61     TH1D* HISTCDF=0; // signal CDF
62    
63     ////////////////////////////////////////////////////////////////////////////////
64     // function definition (not really used; only the integral is used)
65     ////////////////////////////////////////////////////////////////////////////////
66     double FCN(double *x, double *par)
67     {
68     double invmass=x[0];
69     double xs=par[0];
70     double lumi=par[1];
71     double jes=par[2];
72     double jer=par[3];
73     double norm=par[4];
74     double p1=par[5];
75     double p2=par[6];
76     double p3=par[7];
77    
78     double bkg = norm*pow(1.0-invmass/7000.0,p1)/pow(invmass/7000.0,p2+p3*log(invmass/7000.0));
79     double mass=jes*(jer*(invmass-SIGMASS)+SIGMASS);
80     int bin=HIST->GetXaxis()->FindBin(mass);
81     double sig = xs*lumi*HIST->GetBinContent(bin);
82     return bkg+sig;
83     }
84    
85     ////////////////////////////////////////////////////////////////////////////////
86     // function integral
87     ////////////////////////////////////////////////////////////////////////////////
88     double INTEGRAL(double *x0, double *xf, double *par)
89     {
90     double xs=par[0];
91     double lumi=par[1];
92     double jes=par[2];
93     double jer=par[3];
94     double norm=par[4];
95     double p1=par[5];
96     double p2=par[6];
97     double p3=par[7];
98    
99     // uses Simpson's 3/8th rule to compute the background integral over a short interval
100     // also use a power series expansion to determine the intermediate intervals since the pow() call is expensive
101    
102     double dx=(xf[0]-x0[0])/3./7000.;
103     double x=x0[0]/7000.0;
104     double logx=log(x);
105    
106     double a=pow(1-x,p1)/pow(x,p2+p3*logx);
107     double b=dx*a/x/(x-1)*(p2+p1*x-p2*x-2*p3*(x-1)*logx);
108     double c=0.5*dx*dx*a*( (p1-1)*p1/(x-1)/(x-1) - 2*p1*(p2+2*p3*logx)/(x-1)/x + (p2+p2*p2-2*p3+2*p3*logx*(1+2*p2+2*p3*logx))/x/x );
109     double d=0.166666667*dx*dx*dx*a*( (p1-2)*(p1-1)*p1/(x-1)/(x-1)/(x-1) - 3*(p1-1)*p1*(p2+2*p3*logx)/(x-1)/(x-1)/x - (1+p2+2*p3*logx)*(p2*(2+p2) - 6*p3 + 4*p3*logx*(1+p2*p3*logx))/x/x/x + 3*p1*(p2+p2*p2-2*p3+2*p3*logx*(1+2*p2+2*p3*logx))/(x-1)/x/x );
110    
111     double bkg=(xf[0]-x0[0])*norm*(a+0.375*(b+c+d)+0.375*(2*b+4*c+8*d)+0.125*(3*b+9*c+27*d));
112    
113     if(xs==0.0) return bkg;
114    
115     double xprimef=jes*(jer*(xf[0]-SIGMASS)+SIGMASS);
116     double xprime0=jes*(jer*(x0[0]-SIGMASS)+SIGMASS);
117     int bin1=HISTCDF->GetXaxis()->FindBin(xprimef);
118     int bin2=HISTCDF->GetXaxis()->FindBin(xprime0);
119     if(bin1<1) bin1=1;
120     if(bin1>HISTCDF->GetNbinsX()) bin1=HISTCDF->GetNbinsX();
121     if(bin2<1) bin1=1;
122     if(bin2>HISTCDF->GetNbinsX()) bin2=HISTCDF->GetNbinsX();
123     double sig=xs*lumi*(HISTCDF->GetBinContent(bin1)-HISTCDF->GetBinContent(bin2));
124    
125     return bkg+sig;
126     }
127    
128     ////////////////////////////////////////////////////////////////////////////////
129     // main function
130     ////////////////////////////////////////////////////////////////////////////////
131    
132     int main(int argc, char* argv[])
133     {
134     if(argc<=1) {
135     std::cout << "Usage: stats signalmass" << std::endl;
136     return 0;
137     }
138    
139     // setup the signal histogram
140     TFile* histfile=new TFile("Test_Resonance_Shapes.root");
141     histfile->cd();
142     SIGMASS = std::atof(argv[1]);
143     int masspoint = static_cast<int>(SIGMASS);
144     std::ostringstream histname, cdfname;
145     histname << "h_qstar_" << masspoint;
146     cdfname << "h_qstar_" << masspoint << "_cdf";
147     HIST=dynamic_cast<TH1D*>(gROOT->FindObject(histname.str().c_str()));
148     HISTCDF=dynamic_cast<TH1D*>(gROOT->FindObject(cdfname.str().c_str()));
149     assert(HIST && HISTCDF && SIGMASS>0);
150     HIST->Scale(5.); // proper normalization
151    
152     // create the output file
153     TFile* rootfile=new TFile(OUTPUTFILE, "RECREATE"); rootfile->cd();
154    
155     // get the data
156     TH1D* data=getData(INPUTFILE, "data_0", NBINS-1, BOUNDARIES);
157    
158     // setup an initial fitter to perform a background-only fit
159     Fitter initfit(data, INTEGRAL);
160     for(int i=0; i<NPARS; i++) initfit.defineParameter(i, PAR_NAMES[i], PAR_GUESSES[i], PAR_ERR[i], PAR_MIN[i], PAR_MAX[i], PAR_NUIS[i]);
161    
162     // do an initial background-only fit, first
163     for(int i=0; i<NPARS; i++) if(PAR_TYPE[i]==1) initfit.fixParameter(i);
164     initfit.setParameter(POIINDEX, 0.0); // set the POI value to 0
165     initfit.doFit();
166     initfit.calcPull("pull_bkg_init")->Write();
167     initfit.calcDiff("diff_bkg_init")->Write();
168     initfit.write("fit_bkg_init");
169    
170     // setup the limit values
171     double observedLowerBound, observedUpperBound;
172     std::vector<double> expectedLowerBounds;
173     std::vector<double> expectedUpperBounds;
174    
175     // perform the PEs (0 = data)
176     for(int pe=0; pe<=NPES; ++pe) {
177    
178     std::cout << "*********** pe=" << pe << " ***********" << std::endl;
179     std::ostringstream pestr;
180     pestr << "_" << pe;
181    
182     // setup the fitter with the input from the background-only fit
183     TH1D* hist = (pe==0) ? data : initfit.makePseudoData((std::string("data")+pestr.str()).c_str());
184     Fitter fit(hist, INTEGRAL);
185     fit.setPOIIndex(POIINDEX);
186     fit.setPrintLevel(0);
187     for(int i=0; i<NPARS; i++) fit.defineParameter(i, PAR_NAMES[i], initfit.getParameter(i), PAR_ERR[i], PAR_MIN[i], PAR_MAX[i], PAR_NUIS[i]);
188    
189     // perform a background-only fit
190     for(int i=0; i<NPARS; i++) if(PAR_TYPE[i]==1) fit.fixParameter(i);
191     fit.setParameter(POIINDEX, 0.0); // set the POI value to 0
192     fit.doFit();
193     fit.calcPull((std::string("pull_bkg")+pestr.str()).c_str())->Write();
194     fit.calcDiff((std::string("diff_bkg")+pestr.str()).c_str())->Write();
195     fit.write((std::string("fit_bkg")+pestr.str()).c_str());
196    
197     // fix the ranges for the background parameters before calculating the posterior
198     for(int i=0; i<NPARS; i++) {
199     if(PAR_TYPE[i]==0 && PAR_NUIS[i]==1) {
200     double val, err;
201     fit.getParameter(i, val, err);
202     fit.setParLimits(i, val-err, val+err);
203     }
204     }
205    
206     observedLowerBound=0.;
207     observedUpperBound=fit.calculateUpperBoundWithCLs(NSAMPLES, ALPHA);
208    
209    
210     // put the ranges back in place
211     for(int i=0; i<NPARS; i++) {
212     if(PAR_TYPE[i]==0 && PAR_NUIS[i]==1) {
213     fit.setParLimits(i, PAR_MIN[i], PAR_MAX[i]);
214     }
215     }
216    
217     // evaluate the limit
218     /* std::pair<double, double> bounds=evaluateInterval(post, ALPHA, LEFTSIDETAIL);
219     if(pe==0) {
220     observedLowerBound=bounds.first;
221     observedUpperBound=bounds.second;
222     } else {
223     expectedLowerBounds.push_back(bounds.first);
224     expectedUpperBounds.push_back(bounds.second);
225     }*/
226     }
227    
228     ////////////////////////////////////////////////////////////////////////////////
229     // print the results
230     ////////////////////////////////////////////////////////////////////////////////
231    
232     std::cout << "**********************************************************************" << std::endl;
233     for(unsigned int i=0; i<expectedLowerBounds.size(); i++)
234     std::cout << "expected bound(" << (i+1) << ") = [ " << expectedLowerBounds[i] << " , " << expectedUpperBounds[i] << " ]" << std::endl;
235    
236     std::cout << "\nobserved bound = [ " << observedLowerBound << " , " << observedUpperBound << " ]" << std::endl;
237    
238     if(LEFTSIDETAIL>0.0 && NPES>0) {
239     std::cout << "\n***** expected lower bounds *****" << std::endl;
240     double median;
241     std::pair<double, double> onesigma;
242     std::pair<double, double> twosigma;
243     getQuantiles(expectedLowerBounds, median, onesigma, twosigma);
244     std::cout << "median: " << median << std::endl;
245     std::cout << "+/-1 sigma band: [ " << onesigma.first << " , " << onesigma.second << " ] " << std::endl;
246     std::cout << "+/-2 sigma band: [ " << twosigma.first << " , " << twosigma.second << " ] " << std::endl;
247     }
248    
249     if(LEFTSIDETAIL<1.0 && NPES>0) {
250     std::cout << "\n***** expected upper bounds *****" << std::endl;
251     double median;
252     std::pair<double, double> onesigma;
253     std::pair<double, double> twosigma;
254     getQuantiles(expectedUpperBounds, median, onesigma, twosigma);
255     std::cout << "median: " << median << std::endl;
256     std::cout << "+/-1 sigma band: [ " << onesigma.first << " , " << onesigma.second << " ] " << std::endl;
257     std::cout << "+/-2 sigma band: [ " << twosigma.first << " , " << twosigma.second << " ] " << std::endl;
258     }
259    
260     // close the output file
261     rootfile->Close();
262    
263     return 0;
264     }