CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CalibMuon/DTCalibration/src/DTTimeBoxFitter.cc

Go to the documentation of this file.
00001 
00002 /*
00003  *  See header file for a description of this class.
00004  *
00005  *  $Date: 2010/01/08 12:51:42 $
00006  *  $Revision: 1.12 $
00007  *  \author G. Cerminara - INFN Torino
00008  */
00009 
00010 #include "CalibMuon/DTCalibration/interface/DTTimeBoxFitter.h"
00011 
00012 #include <iostream>
00013 #include <vector>
00014 
00015 #include "TFile.h"
00016 #include "TH1F.h"
00017 #include "TMath.h"
00018 #include "TF1.h"
00019 #include "TString.h"
00020 
00021 using namespace std;
00022 
00023 DTTimeBoxFitter::DTTimeBoxFitter(const TString& debugFileName) : hDebugFile(0),
00024                                                                  theVerbosityLevel(0),
00025                                                                  theSigma(10.) {
00026   // Create a root file for debug output only if needed
00027   if(debugFileName != "") hDebugFile = new TFile(debugFileName.Data(), "RECREATE");
00028   interactiveFit = false;
00029   rebin = 1;
00030 }
00031 
00032 
00033 
00034 DTTimeBoxFitter::~DTTimeBoxFitter() {
00035   if(hDebugFile != 0) hDebugFile->Close();
00036 }
00037 
00038 
00039 
00040 
00042 pair<double, double> DTTimeBoxFitter::fitTimeBox(TH1F *hTimeBox) {
00043 
00044     hTimeBox->Rebin(rebin);
00045   
00046   // Check if the histo contains any entry
00047   if(hTimeBox->GetEntries() == 0) {
00048     cout << "[DTTimeBoxFitter]***Error: the time box contains no entry!" << endl;
00049     return make_pair(-1, -1);
00050   }
00051 
00052   if(hTimeBox->GetEntries() < 50000) {
00053     hTimeBox->Rebin(2);
00054   }
00055 
00056   // Get seeds for the fit
00057   // The TimeBox range to be fitted (the rising edge)
00058   double xFitMin=0;     // Min value for the fit
00059   double xFitMax=0;     // Max value for the fit 
00060   double xValue=0;      // The mean value of the gaussian
00061   double xFitSigma=0;   // The sigma of the gaussian
00062   double tBoxMax=0;     // The max of the time box, it is used as seed for gaussian integral
00063 
00064   //hTimeBox->Rebin(2); //FIXME: Temporary for low statistics
00065 
00066   TH1F *hTimeBoxForSeed = (TH1F*) hTimeBox->Clone(); //FIXME: test
00067   if(!interactiveFit) {
00068   getFitSeeds(hTimeBoxForSeed, xValue, xFitSigma, tBoxMax, xFitMin, xFitMax);
00069   } else {
00070     getInteractiveFitSeeds(hTimeBoxForSeed, xValue, xFitSigma, tBoxMax, xFitMin, xFitMax);
00071   }
00072 
00073   // Define the fitting function and use fit seeds
00074   TF1 *fIntGaus = new TF1("IntGauss", intGauss, xFitMin, xFitMax, 3); 
00075   fIntGaus->SetParName(0, "Constant");
00076   fIntGaus->SetParameter(0, tBoxMax);
00077   fIntGaus->SetParName(1, "Mean");
00078   fIntGaus->SetParameter(1, xValue);
00079   fIntGaus->SetParName(2, "Sigma");
00080   fIntGaus->SetParameter(2, xFitSigma);
00081   fIntGaus->SetLineColor(kRed);
00082 
00083 
00084   // Fit the histo
00085   string option = "Q";
00086   if(theVerbosityLevel >= 2)
00087     option = "";
00088 
00089   hTimeBox->Fit("IntGauss", option.c_str(), "",xFitMin, xFitMax);
00090 
00091   // Get fitted parameters
00092   double mean =  fIntGaus->GetParameter("Mean");
00093   double sigma = fIntGaus->GetParameter("Sigma");
00094   //   double constant = fIntGaus->GetParameter("Constant");
00095   double chiSquare = fIntGaus->GetChisquare()/fIntGaus->GetNDF();
00096   
00097   if(theVerbosityLevel >= 1) {
00098     cout << " === Fit Results: " << endl;
00099     cout << "     Fitted mean = " << mean << endl;
00100     cout << "     Fitted sigma = " << sigma << endl;
00101     cout << "     Reduced Chi Square = " << chiSquare << endl;
00102   }
00103   return make_pair(mean, sigma);
00104 }
00105 
00106 
00107 
00108 // Get the seeds for the fit as input from user!It is used if interactiveFit == true
00109 void DTTimeBoxFitter::getInteractiveFitSeeds(TH1F *hTBox, double& mean, double& sigma, double& tBoxMax,
00110                                     double& xFitMin, double& xFitMax) {
00111   if(theVerbosityLevel >= 1)
00112     cout << " === Insert seeds for the Time Box fit:" << endl;
00113   
00114   cout << "Inser the fit mean:" << endl;
00115   cin >> mean;
00116 
00117   sigma = theSigma; //FIXME: estimate it!
00118 
00119   tBoxMax = hTBox->GetMaximum();
00120 
00121   // Define the fit range
00122   xFitMin = mean-5.*sigma;
00123   xFitMax = mean+5.*sigma;
00124 
00125   if(theVerbosityLevel >= 1) {
00126     cout << "      Time Box Rising edge: " << mean << endl;
00127     cout << "    = Seeds and range for fit:" << endl;
00128     cout << "       Seed mean = " << mean << endl;
00129     cout << "       Seed sigma = " << sigma << endl;
00130     cout << "       Fitting from = " << xFitMin << " to " << xFitMax << endl << endl;
00131   }
00132 }
00133 
00134 
00135 // Automatically compute the seeds the range to be used for time box fit
00136 void DTTimeBoxFitter::getFitSeeds(TH1F *hTBox, double& mean, double& sigma, double& tBoxMax,
00137                                     double& xFitMin, double& xFitMax) {
00138   if(theVerbosityLevel >= 1)
00139     cout << " === Looking for fit seeds in Time Box:" << endl;
00140 
00141 
00142   // The approximate width of the time box
00143   static const int tBoxWidth = 400; //FIXE: tune it
00144 
00145   int nBins = hTBox->GetNbinsX();
00146   const int xMin = (int)hTBox->GetXaxis()->GetXmin();
00147   const int xMax = (int)hTBox->GetXaxis()->GetXmax();
00148   const int nEntries =  (int)hTBox->GetEntries();
00149 
00150   double binValue = (double)(xMax-xMin)/(double)nBins;
00151 
00152   // Compute a threshold for TimeBox discrimination
00153   const double threshold = binValue*nEntries/(double)(tBoxWidth*3.);
00154   if(theVerbosityLevel >= 2)
00155     cout << "   Threshold for logic time box is (# entries): " <<  threshold << endl;
00156     
00157   int nRebins = 0; // protection for infinite loop
00158   while(threshold > hTBox->GetMaximum()/2. && nRebins < 5) {
00159     cout << " Rebinning!" << endl;
00160     hTBox->Rebin(2);
00161     nBins = hTBox->GetNbinsX();
00162     binValue = (double)(xMax-xMin)/(double)nBins;
00163     nRebins++;
00164   }
00165 
00166   if(hDebugFile != 0) hDebugFile->cd();
00167   TString hLName = TString(hTBox->GetName())+"L";
00168   TH1F hLTB(hLName.Data(), "Logic Time Box", nBins, xMin, xMax);
00169   // Loop over all time box bins and discriminate them accordigly to the threshold
00170   for(int i = 1; i <= nBins; i++) {
00171     if(hTBox->GetBinContent(i) > threshold)
00172       hLTB.SetBinContent(i, 1);
00173   }
00174   if(hDebugFile != 0) hLTB.Write();
00175   
00176   // Look for the time box in the "logic histo" and save beginning and lenght of each plateau
00177   vector< pair<int, int> > startAndLenght;
00178   if(theVerbosityLevel >= 2)
00179     cout << "   Look for rising and folling edges of logic time box: " << endl;
00180   int start = -1;
00181   int lenght = -1;
00182   for(int j = 1; j < nBins;j++) {
00183     int diff = (int)hLTB.GetBinContent(j+1)-(int)hLTB.GetBinContent(j);
00184     if(diff == 1) { // This is a rising edge
00185       start = j;
00186       lenght = 1;
00187       if(theVerbosityLevel >= 2) {
00188         cout << "     >>>----" << endl;
00189         cout << "      bin: " << j << " is a rising edge" << endl;
00190       }
00191     } else if(diff == -1) { // This is a falling edge
00192       startAndLenght.push_back(make_pair(start, lenght));
00193       if(theVerbosityLevel >= 2) {
00194         cout << "      bin: " << j << " is a falling edge, lenght is: " << lenght << endl;
00195         cout << "     <<<----" << endl;
00196       }
00197       start = -1;
00198       lenght = -1;
00199     } else if(diff == 0 && (int)hLTB.GetBinContent(j) == 1) { // This is a bin within the plateau
00200       lenght ++;
00201     }
00202   }
00203 
00204   if(theVerbosityLevel >= 2)
00205     cout << "   Add macro intervals: " << endl;
00206   // Look for consecutive plateau: 2 plateau are consecutive if the gap is < 5 ns
00207   vector<  pair<int, int> > superIntervals;
00208   for(vector< pair<int, int> >::const_iterator interval = startAndLenght.begin();
00209       interval != startAndLenght.end();
00210       ++interval) {
00211     pair<int, int> theInterval = (*interval);
00212     vector< pair<int, int> >::const_iterator next = interval;
00213     while(++next != startAndLenght.end()) {
00214       int gap = (*next).first - (theInterval.first+theInterval.second);
00215       double gabInNs = binValue*gap;
00216       if(theVerbosityLevel >= 2)
00217         cout << "      gap: " << gabInNs << "(ns)" << endl;
00218       if(gabInNs > 20) {
00219         break;
00220       } else {
00221         theInterval = make_pair(theInterval.first, theInterval.second+gap+(*next).second);
00222         superIntervals.push_back(theInterval);
00223         if(theVerbosityLevel >= 2)
00224           cout << "          Add interval, start: " << theInterval.first
00225                << " width: " << theInterval.second << endl;
00226       }
00227     }
00228   }
00229 
00230   // merge the vectors of intervals
00231   copy(superIntervals.begin(), superIntervals.end(), back_inserter(startAndLenght));
00232 
00233   // Look for the plateau of the right lenght
00234   if(theVerbosityLevel >= 2)
00235     cout << "    Look for the best interval:" << endl;
00236   int delta = 999999;
00237   int beginning = -1;
00238   int tbWidth = -1;
00239   for(vector< pair<int, int> >::const_iterator stAndL = startAndLenght.begin();
00240       stAndL != startAndLenght.end();
00241       stAndL++) {
00242     if(abs((*stAndL).second - tBoxWidth) < delta) {
00243       delta = abs((*stAndL).second - tBoxWidth);
00244       beginning = (*stAndL).first;
00245       tbWidth = (*stAndL).second;
00246       if(theVerbosityLevel >= 2)
00247         cout << "   Candidate: First: " <<  beginning
00248              << ", width: " << tbWidth
00249              << ", delta: " << delta << endl;
00250     }
00251   }
00252 
00253   mean = xMin + beginning*binValue;
00254   sigma = theSigma; //FIXME: estimate it!
00255 
00256   tBoxMax = hTBox->GetMaximum();
00257 
00258   // Define the fit range
00259   xFitMin = mean-5.*sigma;
00260   xFitMax = mean+5.*sigma;
00261 
00262   if(theVerbosityLevel >= 1) {
00263     cout << "      Time Box Rising edge: " << mean << endl;
00264     cout << "      Time Box Width: " << tbWidth*binValue << endl;
00265     cout << "    = Seeds and range for fit:" << endl;
00266     cout << "       Seed mean = " << mean << endl;
00267     cout << "       Seed sigma = " << sigma << endl;
00268     cout << "       Fitting from = " << xFitMin << " to " << xFitMax << endl << endl;
00269   }
00270 }
00271 
00272 
00273 
00274 double intGauss(double *x, double *par) {
00275   double media = par[1];
00276   double sigma = par[2];
00277   double var = (x[0]-media)/(sigma*sqrt(2.));
00278 
00279   return 0.5*par[0]*(1+TMath::Erf(var));
00280 
00281 }