00001 // @(#)root/physics:$Id: TFeldmanCousins.cxx 30837 2009-10-23 07:02:49Z moneta $ 00002 // Author: Adrian Bevan 2001 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * 00006 * Copyright (C) 2001, Liverpool University. * 00007 * All rights reserved. * 00008 * * 00009 * For the licensing terms see $ROOTSYS/LICENSE. * 00010 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00011 *************************************************************************/ 00012 00013 //////////////////////////////////////////////////////////////////////////// 00014 // TFeldmanCousins 00015 // 00016 // class to calculate the CL upper limit using 00017 // the Feldman-Cousins method as described in PRD V57 #7, p3873-3889 00018 // 00019 // The default confidence interval calvculated using this method is 90% 00020 // This is set either by having a default the constructor, or using the 00021 // appropriate fraction when instantiating an object of this class (e.g. 0.9) 00022 // 00023 // The simple extension to a gaussian resolution function bounded at zero 00024 // has not been addressed as yet -> `time is of the essence' as they write 00025 // on the wall of the maze in that classic game ... 00026 // 00027 // VARIABLES THAT CAN BE ALTERED 00028 // ----------------------------- 00029 // => depending on your desired precision: The intial values of fMuMin, 00030 // fMuMax, fMuStep and fNMax are those used in the PRD: 00031 // fMuMin = 0.0 00032 // fMuMax = 50.0 00033 // fMuStep= 0.005 00034 // but there is total flexibility in changing this should you desire. 00035 // 00036 // 00037 // see example of use in $ROOTSYS/tutorials/math/FeldmanCousins.C 00038 // 00039 // see note about: "Should I use TRolke, TFeldmanCousins, TLimit?" 00040 // in the TRolke class description. 00041 // 00042 // Author: Adrian Bevan, Liverpool University 00043 // 00044 // Copyright Liverpool University 2001 bevan@slac.stanford.edu 00045 /////////////////////////////////////////////////////////////////////////// 00046 00047 #include "Riostream.h" 00048 #include "TMath.h" 00049 #include "TFeldmanCousins.h" 00050 00051 ClassImp(TFeldmanCousins) 00052 00053 //______________________________________________________________________________ 00054 TFeldmanCousins::TFeldmanCousins(Double_t newFC, TString options) 00055 { 00056 //constructor 00057 fCL = newFC; 00058 fUpperLimit = 0.0; 00059 fLowerLimit = 0.0; 00060 fNobserved = 0.0; 00061 fNbackground = 0.0; 00062 options.ToLower(); 00063 if (options.Contains("q")) fQUICK = 1; 00064 else fQUICK = 0; 00065 00066 fNMax = 50; 00067 fMuStep = 0.005; 00068 SetMuMin(); 00069 SetMuMax(); 00070 SetMuStep(); 00071 } 00072 00073 00074 //______________________________________________________________________________ 00075 TFeldmanCousins::~TFeldmanCousins() 00076 { 00077 } 00078 00079 00080 //______________________________________________________________________________ 00081 Double_t TFeldmanCousins::CalculateLowerLimit(Double_t Nobserved, Double_t Nbackground) 00082 { 00083 //////////////////////////////////////////////////////////////////////////////////////////// 00084 // given Nobserved and Nbackground, try different values of mu that give lower limits that// 00085 // are consistent with Nobserved. The closed interval (plus any stragglers) corresponds // 00086 // to the F&C interval // 00087 //////////////////////////////////////////////////////////////////////////////////////////// 00088 00089 CalculateUpperLimit(Nobserved, Nbackground); 00090 return fLowerLimit; 00091 } 00092 00093 00094 //______________________________________________________________________________ 00095 Double_t TFeldmanCousins::CalculateUpperLimit(Double_t Nobserved, Double_t Nbackground) 00096 { 00097 //////////////////////////////////////////////////////////////////////////////////////////// 00098 // given Nobserved and Nbackground, try different values of mu that give upper limits that// 00099 // are consistent with Nobserved. The closed interval (plus any stragglers) corresponds // 00100 // to the F&C interval // 00101 //////////////////////////////////////////////////////////////////////////////////////////// 00102 00103 fNobserved = Nobserved; 00104 fNbackground = Nbackground; 00105 00106 Double_t mu = 0.0; 00107 00108 // for each mu construct the ranked table of probabilities and test the 00109 // observed number of events with the upper limit 00110 Double_t min = -999.0; 00111 Double_t max = 0; 00112 Int_t iLower = 0; 00113 00114 Int_t i; 00115 for(i = 0; i <= fNMuStep; i++) { 00116 mu = fMuMin + (Double_t)i*fMuStep; 00117 Int_t goodChoice = FindLimitsFromTable( mu ); 00118 if( goodChoice ) { 00119 min = mu; 00120 iLower = i; 00121 break; 00122 } 00123 } 00124 00125 //================================================================== 00126 // For quicker evaluation, assume that you get the same results when 00127 // you expect the uppper limit to be > Nobserved-Nbackground. 00128 // This is certainly true for all of the published tables in the PRD 00129 // and is a reasonable assumption in any case. 00130 //================================================================== 00131 00132 Double_t quickJump = 0.0; 00133 if (fQUICK) quickJump = Nobserved-Nbackground-fMuMin; 00134 if (quickJump < 0.0) quickJump = 0.0; 00135 00136 for(i = iLower+1; i <= fNMuStep; i++) { 00137 mu = fMuMin + (Double_t)i*fMuStep + quickJump; 00138 Int_t goodChoice = FindLimitsFromTable( mu ); 00139 if( !goodChoice ) { 00140 max = mu; 00141 break; 00142 } 00143 } 00144 00145 fUpperLimit = max; 00146 fLowerLimit = min; 00147 00148 return max; 00149 } 00150 00151 00152 //______________________________________________________________________________ 00153 Int_t TFeldmanCousins::FindLimitsFromTable( Double_t mu ) 00154 { 00155 /////////////////////////////////////////////////////////////////// 00156 // calculate the probability table for a given mu for n = 0, NMAX// 00157 // and return 1 if the number of observed events is consistent // 00158 // with the CL bad // 00159 /////////////////////////////////////////////////////////////////// 00160 00161 Double_t *p = new Double_t[fNMax]; //the array of probabilities in the interval MUMIN-MUMAX 00162 Double_t *r = new Double_t[fNMax]; //the ratio of likliehoods = P(Mu|Nobserved)/P(MuBest|Nobserved) 00163 Int_t *rank = new Int_t[fNMax]; //the ranked array corresponding to R (largest first) 00164 Double_t *muBest = new Double_t[fNMax]; 00165 Double_t *probMuBest = new Double_t[fNMax]; 00166 00167 //calculate P(i | mu) and P(i | mu)/P(i | mubest) 00168 Int_t i; 00169 for(i = 0; i < fNMax; i++) { 00170 muBest[i] = (Double_t)(i - fNbackground); 00171 if(muBest[i]<0.0) muBest[i] = 0.0; 00172 probMuBest[i] = Prob(i, muBest[i], fNbackground); 00173 p[i] = Prob(i, mu, fNbackground); 00174 if(probMuBest[i] == 0.0) r[i] = 0.0; 00175 else r[i] = p[i]/probMuBest[i]; 00176 } 00177 00178 //rank the likelihood ratio 00179 TMath::Sort(fNMax, r, rank); 00180 00181 //search through the probability table and get the i for the CL 00182 Double_t sum = 0.0; 00183 Int_t iMax = rank[0]; 00184 Int_t iMin = rank[0]; 00185 for(i = 0; i < fNMax; i++) { 00186 sum += p[rank[i]]; 00187 if(iMax < rank[i]) iMax = rank[i]; 00188 if(iMin > rank[i]) iMin = rank[i]; 00189 if(sum >= fCL) break; 00190 } 00191 00192 delete [] p; 00193 delete [] r; 00194 delete [] rank; 00195 delete [] muBest; 00196 delete [] probMuBest; 00197 00198 if((fNobserved <= iMax) && (fNobserved >= iMin)) return 1; 00199 else return 0; 00200 } 00201 00202 00203 //______________________________________________________________________________ 00204 Double_t TFeldmanCousins::Prob(Int_t N, Double_t mu, Double_t B) 00205 { 00206 //////////////////////////////////////////////// 00207 // calculate the poissonian probability for // 00208 // a mean of mu+B events with a variance of N // 00209 //////////////////////////////////////////////// 00210 00211 return TMath::Poisson( N, mu+B); 00212 } 00213 00214 //______________________________________________________________________________ 00215 void TFeldmanCousins::SetMuMax(Double_t newMax) 00216 { 00217 //set maximum value of signal to use in calculating the tables 00218 fMuMax = newMax; 00219 fNMax = (Int_t)newMax; 00220 SetMuStep(fMuStep); 00221 } 00222 00223 //______________________________________________________________________________ 00224 void TFeldmanCousins::SetMuStep(Double_t newMuStep) 00225 { 00226 //set the step in signal to use when generating tables 00227 if(newMuStep == 0.0) { 00228 cout << "TFeldmanCousins::SetMuStep ERROR New step size is zero - unable to change value"<< endl; 00229 return; 00230 } else { 00231 fMuStep = newMuStep; 00232 fNMuStep = (Int_t)((fMuMax - fMuMin)/fMuStep); 00233 } 00234 }