Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Related Pages

OpeTool.cpp

00001 #include "OpeTool.h"
00002 #include "SctData/RawScanResult.h"
00003 #include "Sct/LogicErrors.h"
00004 #include <boost/shared_ptr.hpp>
00005 
00006 #include "TH2.h"
00007 #include "TH1.h"
00008 #include "TMath.h"
00009 #include "TFile.h"
00010 
00011 using namespace SctData;
00012 using namespace Sct;
00013 using boost::shared_ptr;
00014 
00015 namespace SctAnalysis {
00016 
00017   OpeTool::OpeTool(){}
00018 
00019   OpeTool::~OpeTool(){}
00020 
00021   boost::shared_ptr<SctData::OpeResult> OpeTool::analyzeModule(const RawScanResult& raw){
00022 
00023     unsigned nOPE = raw.nOccupancyPerEvent();
00024 
00025     shared_ptr<OpeResult> result;
00026     if (nOPE==0) return result;
00027     
00028     result = shared_ptr<OpeResult>(new OpeResult(raw.getUniqueID()));
00029 
00030     //For each chip... 
00031     for (unsigned int ichip=0; ichip<nOPE; ++ichip) {
00032       const TH2D& chipHist = raw.getOccupancyPerEvent(ichip);
00033       const int biny = chipHist.GetNbinsY();
00034 
00035       std::ostringstream newhistname;
00036       newhistname << raw.getClassName() << "." << raw.getUniqueID() 
00037           << "_Chip" << ichip << "_Ope_Badness"; 
00038 
00039       std::ostringstream newtitle;
00040       newtitle << "Chip" << ichip << "_Ope_Badness"; 
00041 
00042       const char* c_name=newhistname.str().c_str();
00043       const char* c_title=newtitle.str().c_str();
00044       // due to Brun's incompetence we need to make a non-const number of bins :(
00045       int stupidBloomingNonConstBinY=biny;
00046       shared_ptr<TH1> badnessHist(new TH1D(c_name, c_title, stupidBloomingNonConstBinY, chipHist.GetYaxis()->GetXbins()->GetArray()));
00047 
00048       // loop over y bins making projections
00049       for(unsigned int iy=1; iy<biny+1; ++iy){
00050     std::ostringstream projectionName;
00051     projectionName << raw.getClassName() << "." << raw.getUniqueID() 
00052                << "_Chip" << ichip << "_bin" << iy; 
00053     shared_ptr<TH1D> proj(chipHist.ProjectionX(projectionName.str().c_str(),iy,iy,""));
00054     //  std::cout << "OPE: Bin " << iy << " ...." 
00055     //    << findChi2Binomial(*proj) << " fraction :"  << fractionVariance(*proj) <<std::endl;
00056     // std::cout << "OPE: Chip: " << ichip << " Bin " << iy << "threshold: " << chipHist.GetYaxis()->GetBinCenter(iy) <<" fraction :"  << fractionVariance(*proj) <<std::endl;
00057     badnessHist->SetBinContent(iy, fractionVariance(*proj));    
00058       }
00059 
00060       SctData::ChipOpeResult& chipResult=result->getChipResult(ichip);
00061 
00062       // FILL IN THAT CHIP + give max
00063       chipResult.hist=badnessHist;
00064       chipResult.badmax= badnessHist->GetMaximum();
00065       int badbin = badnessHist->GetMaximumBin();
00066       chipResult.threshold= badnessHist->GetBinCenter(badbin);
00067     } 
00068     
00069     return result;
00070   }
00071 
00072   double OpeTool::fractionVariance(const TH1& data) {
00073 
00074     double range = data.GetXaxis()->GetXmax() - data.GetXaxis()->GetXmin();
00075     double prob = (data.GetMean())/range;
00076     // theoretically calculate the RMS from the probability dist:
00077     double calcRMS = sqrt(range*prob*(1-prob));
00078     // measure the RMS from data
00079     double measRMS = data.GetRMS();
00080     // return the fraction of the measured and calculated RMS
00081     // std::cout << "OPE: measuredRMS :" << measRMS << " calcRMS :" << calcRMS << std::endl;    
00082     if (calcRMS ==0) return 1;
00083     else return measRMS/calcRMS;
00084   }
00085   
00086   double OpeTool::findChi2Binomial(const TH1& data) {
00087 
00088     const unsigned int binx = data.GetNbinsX();
00089     unsigned int dof = 0;
00090     double trials = data.GetSumOfWeights();
00091     double range = data.GetXaxis()->GetXmax() - data.GetXaxis()->GetXmin();
00092     if (range==0.) throw Sct::LogicError("Range of histogram x axis was zero!",__FILE__,__LINE__);
00093     double prob = (data.GetMean())/range;
00094     std::cout << "OPE: Mean:" << data.GetMean()<< std::endl;    
00095 
00096     double chisq =0;
00097     double delta =0;
00098 
00099     if (prob == 0) return 0;
00100     else {
00101       // Root counts bin numbers starting from 1
00102       // the first bin goes from -0.5 to 0.5 -- no physical meaning 
00103       // because a trigger requires an event... 
00104       // the following bins (0.5,4.5), (4.5,8.5) and so on... 
00105       for (unsigned int ix=1; ix<binx+1; ix++){
00106     
00107     // to make the computation easier and faster, calculate only for those bins which have data in it... 
00108     if (data.GetBinContent(ix) > 0) {
00109       
00110       // want to sum over all ints greater than (the first int above the lower bin edge) 
00111       // but less than (the first int above the upper bin edge)
00112       int start = static_cast<int>(ceil(data.GetBinLowEdge(ix)));
00113       int w = int(data.GetBinWidth(ix));
00114       if (w ==0) throw Sct::LogicError("Error- bin size truncates to zero!", __FILE__, __LINE__);
00115       std::cout << "Giving BinomialI " << prob << "range: " << start << " to " << start+w << std::endl;
00116       int irange=static_cast<int>(floor(range+0.5));
00117       double expect =  (BinomialI(prob,irange,start) - 
00118                 BinomialI(prob,irange,start+w))*trials;
00119       
00120       if (expect ==0) delta = data.GetBinContent(ix);
00121       else delta  = (data.GetBinContent(ix)-expect)/sqrt(expect);
00122       
00123       chisq += delta*delta;
00124       std::cout << "OPE: expect:" << expect<< " get: "<<data.GetBinContent(ix) << " delta:" << delta << std::endl;  
00125       dof += 1;
00126     }
00127       }
00128       // binomial distribution has one empty parameter.. 
00129       dof = dof -1;
00130       if (dof == 0 ) return 0;
00131       else return sqrt(chisq)/(dof-1);
00132     }
00133   }
00134   // The following has been copied from the latest ROOT libraries since the 
00135   // installed ROOT libraries are not necessarily the latest
00136   double OpeTool::BinomialI(Double_t p, Int_t n, Int_t k)
00137     {
00138       // Suppose an event occurs with probability _p_ per trial
00139       // Then the probability P of its occuring _k_ or more times
00140       // in _n_ trials is termed a cumulative binomial probability
00141       // the formula is P = sum_from_j=k_to_n(TMath::Binomial(n, j)*
00142       // *TMath::Power(p, j)*TMath::Power(1-p, n-j)
00143       // For _n_ larger than 12 BetaIncomplete is a much better way
00144       // to evaluate the sum than would be the straightforward sum calculation
00145       // for _n_ smaller than 12 either method is acceptable
00146       // ("Numerical Recipes")
00147       //     --implementation by Anna Kreshuk
00148       
00149       Double_t P = BetaIncomplete(p, Double_t(k), Double_t(n-k+1));
00150       return P;
00151     }
00152   
00153   Double_t OpeTool::BetaIncomplete(Double_t x, Double_t a, Double_t b)
00154     {
00155       // Calculates the incomplete Beta-function.
00156       //  -- implementation by Anna Kreshuk
00157       
00158       Double_t bt;
00159       if ((x<0.0)||(x>1.0)) {
00160     throw Sct::LogicError("OpeTool::BetaIncomplete: X must between 0 and 1", __FILE__, __LINE__);
00161     return 0.0;
00162       }
00163       if ((x==0.0)||(x==1.0)) {
00164     bt=0.0;
00165       } else {
00166     bt = TMath::Power(x, a)*TMath::Power(1-x, b)/Beta(a, b);
00167       }
00168       if (x<(a+1)/(a+b+2)) {
00169     return bt*BetaCf(x, a, b)/a;
00170       }
00171       else {
00172     return (1 - bt*BetaCf(1-x, b, a)/b);
00173       }
00174     }
00175   
00176  Double_t OpeTool::Beta(Double_t p, Double_t q)
00177 {
00178    // Calculates Beta-function Gamma(p)*Gamma(q)/Gamma(p+q).
00179 
00180    return TMath::Exp(TMath::LnGamma(p)+TMath::LnGamma(q)-TMath::LnGamma(p+q));
00181 }
00182 
00183   Double_t OpeTool::BetaCf(Double_t x, Double_t a, Double_t b)
00184     {
00185       // Continued fraction evaluation by modified Lentz's method
00186       // used in calculation of incomplete Beta function.
00187       
00188       Int_t itmax = 500;
00189       Double_t eps = 3.e-14;
00190       Double_t fpmin = 1.e-30;
00191       
00192       Int_t m, m2;
00193       Double_t aa, c, d, del, qab, qam, qap;
00194       Double_t h;
00195       qab = a+b;
00196       qap = a+1.0;
00197       qam = a-1.0;
00198       c = 1.0;
00199       d = 1.0 - qab*x/qap;
00200       if (TMath::Abs(d)<fpmin) d=fpmin;
00201       d=1.0/d;
00202       h=d;
00203       for (m=1; m<=itmax; m++) {
00204     m2=m*2;
00205     aa = m*(b-m)*x/((qam+ m2)*(a+m2));
00206     d = 1.0 +aa*d;
00207     if(TMath::Abs(d)<fpmin) d = fpmin;
00208     c = 1 +aa/c;
00209     if (TMath::Abs(c)<fpmin) c = fpmin;
00210     d=1.0/d;
00211     h*=d*c;
00212     aa = -(a+m)*(qab +m)*x/((a+m2)*(qap+m2));
00213     d=1.0+aa*d;
00214     if(TMath::Abs(d)<fpmin) d = fpmin;
00215     c = 1.0 +aa/c;
00216     if (TMath::Abs(c)<fpmin) c = fpmin;
00217     d=1.0/d;
00218     del = d*c;
00219     h*=del;
00220     if (TMath::Abs(del-1)<=eps) break;
00221       }
00222       if (m>itmax) {
00223     throw Sct::LogicError("OpeTool::BetaCf: a or b too big, or itmax too small", __FILE__, __LINE__);
00224       }
00225       return h;
00226     }
00227 }

Generated on Thu Feb 3 17:37:38 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5