// File: runSigCalc.cc // Glen Cowan // RHUL Physics // 14 April 2008 // Simple driver program for the function getSignificance, which // returns the significance with which one can reject a hypothesized // signal strength parameter mu. (For discovery, one rejects mu = 0.) // Input: runSigCalc reads in a text file with the input data. // Lines beginning with # are comments. // The first (non-comment) line contains the target luminosity. // The second (non-comment) line contains the accepted number of // signal events from MC and the luminosity of the signal MC sample. // // On subsequent lines the user lists for each background component the // accepted number of background events m and the effective luminosity // L_MC used to generate the background sample. #include #include #include #include #include #include #include #include #include #include #include "SigCalc.h" #include "getDiscoverySignificance.h" #include "getExclusionSignificance.h" using namespace std; int main(int argc, char **argv) { TFile* histFile = new TFile("SigCalc.root", "recreate"); TH1D* h_q0 = new TH1D("h_q0", "q0", 200, 0., 100.); TH1D* h_muHat = new TH1D("h_muHat", "muHat", 200, -10., 10.); TH1D* h_lambdaHat = new TH1D("h_lambdaHat", "lambdaHat", 200, -5, 5); TH1D* h_sigmaHat = new TH1D("h_sigmaHat", "sigmaHat", 200, 0., 10.); TH1D* h_omegaHat = new TH1D("h_omegaHat", "omegaHat", 200, 0., 2.); // versions of histograms with exponentially distributed weights ("ew") TH1D* h_q0_ew = new TH1D("h_q0_ew", "q0", 200, 0., 100.); TH1D* h_muHat_ew = new TH1D("h_muHat_ew", "muHat", 200, -10., 10.); TH1D* h_lambdaHat_ew = new TH1D("h_lambdaHat_ew", "lambdaHat", 200, -5, 5); TH1D* h_sigmaHat_ew = new TH1D("h_sigmaHat_ew", "sigmaHat", 200, 0., 10.); TH1D* h_omegaHat_ew = new TH1D("h_omegaHat_ew", "omegaHat", 200, 0., 2.); int seed = 12348; TRandom3* ran = new TRandom3(seed); // Read input file string inputFileName; if ( argc == 1 ) { cout << "Enter name of input file: "; cin >> inputFileName; cin.ignore(); // clear buffer } else { inputFileName = argv[1]; } ifstream f; f.open( inputFileName.c_str() ); if ( f.fail() ){ cout << "Sorry, couldn't open input file" << endl; exit(1); } int option; double nObs, s, mu; vector mObs; vector tau; vector S1Obs; vector S2Obs; vector bVec; vector aVec; vector xiVec; vector lambdaVec; vector sigmaVec; istringstream instream; // Declare an input string stream string line; int lineNum = 0; while ( getline(f, line) ) { bool useLine = !( line.substr(0,1) == "#" || line.substr(0,1) == "!"); if ( useLine ) { instream.clear(); // Reset from possible previous errors instream.str(line); // Use line as source of input lineNum++; if ( lineNum == 1 ) { instream >> option; } if ( option%100 == 0 ) { // rest of info is a data set if ( lineNum == 2 ) { instream >> nObs >> s; } else if ( lineNum > 2 ) { double mObs_i, tau_i, S1Obs_i, S2Obs_i, wsum, w2sum; instream >> mObs_i >> tau_i >> S1Obs_i >> S2Obs_i >> wsum >> w2sum; mObs.push_back(mObs_i); tau.push_back(tau_i); S1Obs.push_back(S1Obs_i); S2Obs.push_back(S2Obs_i); } } // option == 0 else if ( option%100 == 1 ){ // rest of info are parameters if ( lineNum == 2 ) { instream >> mu >> s; } else if ( lineNum > 2 ) { double tau_i, b_i, a_i, xi_i; instream >> b_i >> tau_i >> a_i >> xi_i; tau.push_back(tau_i); bVec.push_back(b_i); aVec.push_back(a_i); xiVec.push_back(xi_i); } } // option == 1 } // useline } // while getline if ( option%100 == 1 ){ // generate data set SigCalc* sc = new SigCalc (s, tau, mu, bVec, aVec, xiVec, ran, option); nObs = sc->n(); for (int i=0; im(i)); S1Obs.push_back(sc->S1(i)); S2Obs.push_back(sc->S2(i)); cout << tau[i] << " " << bVec[i] << " " << aVec[i] << " " << xiVec[i] << endl; cout << "nObs = " << nObs << endl; cout << "m, S1, S2 = " << mObs[i] << " " << S1Obs[i] << " " << S2Obs[i] << endl; if ( option == 1 ) { // w ~ log normal double z = 1. - exp(-aVec[i]/xiVec[i]); double lambda = log (aVec[i]/(xiVec[i]*z)) - 0.5*aVec[i]/xiVec[i]; double sigma_l = (aVec[i]/xiVec[i]) / sqrt(12.); cout << "corresponding lambda, sigma_l = " << lambda << " " << sigma_l << endl; lambdaVec.push_back(lambda); sigmaVec.push_back(sigma_l); } else if ( option == 101 || option == 201 ) { // w ~ Gauss double z = 1. - exp(-aVec[i]/xiVec[i]); double sigma_w = (0.5*aVec[i]/xiVec[i]) * (1. - exp(-2*aVec[i]/xiVec[i])) / (z*z) - 1.; double omega = 1.; // KLUDGE, use lambdaVec to hold the omega values. // Here sigma means sigma_w lambdaVec.push_back(omega); sigmaVec.push_back(sigma_w); } } delete sc; } int numBkg = mObs.size(); cout << "numBkg = " << numBkg << endl; cout << "n = " << nObs << endl; cout << "s = " << s << endl; // Get prelim. estimate of btot. Different prescription depending // on whether w ~ log-normal or Gaussian double btotHat = 0.; for (int i=0; i= 100 && option < 200 ) { // w ~ Gaussian bHat_i = S1Obs[i]/tau[i]; } else if ( option >= 200 && option < 300 ) { // bHat ~ Gaussian bHat_i = S1Obs[i]/tau[i]; } btotHat += bHat_i; cout << "prelim. i, bHat_i = " << i << " " << bHat_i << endl; } cout << "prelim. estimated total background = " << btotHat << endl; cout << endl; double ZDisc = getDiscoverySignificance(nObs, s, mObs, tau, S1Obs, S2Obs, option); cout << "Asymptotic discovery significance Z = " << ZDisc << endl; cout << "Corresponding p-value = " << 1. - TMath::Freq(ZDisc) << endl; cout << endl; double muTest; // muTest = 1.0; // for defining lambda(mu) // double ZExcl = getExclusionSignificance(muTest, nObs, s, mObs, tau, // S1Obs, S2Obs); // cout << "Asymptotic exclusion significance for mu = " << muTest // << " is Z = " << ZExcl << endl; // cout << "Corresponding p-value = " << 1. - TMath::Freq(ZExcl) << endl; // Now redo discovery analysis without using asymptotic formulae. // First step is to get HatHat(0) values for nuisance parameters muTest = 0.; SigCalc* sc = new SigCalc(nObs, s, mObs, tau, S1Obs, S2Obs, option); double muHatObs = (nObs - btotHat) / s; // start value in fit vector bHatObs(numBkg); vector bHatHatObs(numBkg); vector lambdaHatObs(numBkg); vector lambdaHatHatObs(numBkg); vector sigmaHatObs(numBkg); vector sigmaHatHatObs(numBkg); double q0Obs = sc->q0(muHatObs, bHatObs, bHatHatObs, lambdaHatObs, lambdaHatHatObs, sigmaHatObs, sigmaHatHatObs); cout << "muHatObs = " << muHatObs << endl; for (int i=0; i bHat(numBkg); vector bHatHat(numBkg); vector lambdaHat(numBkg); vector lambdaHatHat(numBkg); vector sigmaHat(numBkg); vector sigmaHatHat(numBkg); double q0 = sc->q0(muHat, bHat, bHatHat, lambdaHat, lambdaHatHat, sigmaHat, sigmaHatHat); delete sc; h_q0->Fill(q0); h_muHat->Fill(muHat); h_lambdaHat->Fill(lambdaHat[0]); h_sigmaHat->Fill(sigmaHat[0]); // KLUDGE -- for w ~ Gauss, lambdaHat, lambdaHatHat actually // holds omegaHat, omegaHatHat. double omegaHat; if ( option < 100 ) { omegaHat = exp(lambdaHat[0] + 0.5*sigmaHat[0]*sigmaHat[0]); } else if ( option >= 100 && option < 200 ) { omegaHat = lambdaHat[0]; } h_omegaHat->Fill(omegaHat); // cout << "runSigCalc: q0, q0Obs = " << q0 << " " << q0Obs << endl; if (q0 >= q0Obs) { numRej++; } if ( i%(numExp/100) == 0 ) { cout << "generated experiment " << i << endl; } } cout << numRej << " events rejected out of " << numExp << " generated." << endl; double p0 = static_cast(numRej)/static_cast(numExp); double Z0 = TMath::NormQuantile(1. - p0); cout << "MC Z0 (data ~ log-normal weights) = " << Z0 << endl; // Now do this again but generate the data according to the // "real" model with a and xi (not quite w ~ log-normal). // Only do this if a and xi available, i.e., data was generated if ( option%100 == 1 ) { numRej = 0; for (int i=0; iPoisson(muTest*s + bHatHatObsTot); double nd = static_cast(nGen); vector md; md.clear(); vector S1Gen; S1Gen.clear(); vector S2Gen; S2Gen.clear(); for (int j=0; j= 100 && option < 300) { omega_j = lambdaHatHatObs[j]; } int mGen = ran->Poisson(tau[j]*bHatHatObs[j]/omega_j); md.push_back(static_cast(mGen)); double S1 = 0.; double S2 = 0.; for (int k=0; kRndm(); // uniform in ]0,1] double x = aVec[j]*r; double w = aVec[j] * (1./xiVec[j])*exp(-x/xiVec[j]) / (1 - exp(-aVec[j]/xiVec[j])); double lnw = log(w); if ( option < 100 ) { S1 += log(w); S2 += lnw*lnw; } else if ( option >= 100 && option < 300 ){ S1 += w; S2 += w*w; } // cout << w << " " << lnw << endl; } S1Gen.push_back(S1); S2Gen.push_back(S2); // cout << "m, S1, S2... " << mGen << " " << S1 << " " << S2 << endl; } SigCalc* sc = new SigCalc(nd, s, md, tau, S1Gen, S2Gen, option); double muHat = (nd - bHatHatObsTot) / s; // start value in fit vector bHat(numBkg); vector bHatHat(numBkg); vector lambdaHat(numBkg); vector lambdaHatHat(numBkg); vector sigmaHat(numBkg); vector sigmaHatHat(numBkg); double q0 = sc->q0(muHat, bHat, bHatHat, lambdaHat, lambdaHatHat, sigmaHat, sigmaHatHat); delete sc; h_q0_ew->Fill(q0); h_muHat_ew->Fill(muHat); h_lambdaHat_ew->Fill(lambdaHat[0]); h_sigmaHat_ew->Fill(sigmaHat[0]); // KLUDGE -- for w ~ Gauss, lambdaHat, lambdaHatHat actually // holds omegaHat, omegaHatHat. double omegaHat_ew; if ( option < 100 ) { omegaHat_ew = exp(lambdaHat[0] + 0.5*sigmaHat[0]*sigmaHat[0]); } else if ( option >= 100 && option < 200 ) { omegaHat_ew = lambdaHat[0]; } h_omegaHat_ew->Fill(omegaHat_ew); // cout << "runSigCalc: q0, q0Obs = " << q0 << " " << q0Obs << endl; if (q0 >= q0Obs) { numRej++; } if ( i%(numExp/10) == 0 ) { cout << "generated experiment " << i << endl; } } cout << "with exponentially distributed weights: " << endl; cout << numRej << " events rejected out of " << numExp << " generated." << endl; p0 = static_cast(numRej)/static_cast(numExp); Z0 = TMath::NormQuantile(1. - p0); cout << "MC Z0 (data ~ exponential weights) = " << Z0 << endl; } // option == 1 (w ~ exp) cout << tau[0] << " " << ZDisc << " " << Z0 << endl; histFile->Write(); histFile->Close(); return 0; }