00001
00002
00003
00004
00005
00006
00007
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
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
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
00057
00058 double xFitMin=0;
00059 double xFitMax=0;
00060 double xValue=0;
00061 double xFitSigma=0;
00062 double tBoxMax=0;
00063
00064
00065
00066 TH1F *hTimeBoxForSeed = (TH1F*) hTimeBox->Clone();
00067 if(!interactiveFit) {
00068 getFitSeeds(hTimeBoxForSeed, xValue, xFitSigma, tBoxMax, xFitMin, xFitMax);
00069 } else {
00070 getInteractiveFitSeeds(hTimeBoxForSeed, xValue, xFitSigma, tBoxMax, xFitMin, xFitMax);
00071 }
00072
00073
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
00085 string option = "Q";
00086 if(theVerbosityLevel >= 2)
00087 option = "";
00088
00089 hTimeBox->Fit("IntGauss", option.c_str(), "",xFitMin, xFitMax);
00090
00091
00092 double mean = fIntGaus->GetParameter("Mean");
00093 double sigma = fIntGaus->GetParameter("Sigma");
00094
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
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;
00118
00119 tBoxMax = hTBox->GetMaximum();
00120
00121
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
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
00143 static const int tBoxWidth = 400;
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
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;
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
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
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) {
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) {
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) {
00200 lenght ++;
00201 }
00202 }
00203
00204 if(theVerbosityLevel >= 2)
00205 cout << " Add macro intervals: " << endl;
00206
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
00231 copy(superIntervals.begin(), superIntervals.end(), back_inserter(startAndLenght));
00232
00233
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;
00255
00256 tBoxMax = hTBox->GetMaximum();
00257
00258
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 }