CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CalibTracker/SiStripLorentzAngle/src/SymmetryFit.cc

Go to the documentation of this file.
00001 #include "CalibTracker/SiStripLorentzAngle/interface/SymmetryFit.h"
00002 #include <cmath>
00003 #include <cassert>
00004 #include "boost/foreach.hpp"
00005 
00006 TH1* SymmetryFit::symmetryChi2(std::string basename, const std::vector<TH1*>& candidates, const std::pair<unsigned,unsigned> range)
00007 {
00008   TH1* fake = (TH1*)(candidates[0]->Clone(basename.c_str())); 
00009   fake->Reset();
00010   SymmetryFit combined(fake,range);
00011   delete fake;
00012 
00013   BOOST_FOREACH(const TH1* candidate, candidates) {
00014     SymmetryFit sf(candidate,range); 
00015     combined+=sf; 
00016     delete sf.chi2_; 
00017   }
00018 
00019   int status = combined.fit();
00020   if(status) { delete combined.chi2_; combined.chi2_=0;}
00021   return combined.chi2_;
00022 }
00023 
00024 TH1* SymmetryFit::symmetryChi2(const TH1* candidate, const std::pair<unsigned,unsigned> range) 
00025 {
00026   SymmetryFit sf(candidate, range);
00027   int status = sf.fit();
00028   if(status) { delete sf.chi2_; sf.chi2_=0; }
00029   return sf.chi2_;
00030 }
00031 
00032 SymmetryFit::SymmetryFit(const TH1* h, const std::pair<unsigned,unsigned> r)
00033   : symm_candidate_(h), 
00034     minDF_(r.second-r.first),
00035     range_(r),
00036     minmaxUsable_(findUsableMinMax()),
00037     ndf_( minmaxUsable_.first<minmaxUsable_.second ? minmaxUsable_.second-minmaxUsable_.first : 0),
00038     chi2_(0)
00039 {
00040   makeChi2Histogram();
00041   fillchi2();
00042 }
00043 
00044 void SymmetryFit::makeChi2Histogram() 
00045 {
00046   std::string XXname = name(symm_candidate_->GetName());
00047   unsigned Nbins = 2*( range_.second - range_.first ) + 1;
00048   double binwidth = symm_candidate_->GetBinWidth(1);
00049   double low = symm_candidate_->GetBinCenter(range_.first) - 3*binwidth/4;
00050   double up = symm_candidate_->GetBinCenter(range_.second-1) + 3*binwidth/4;
00051   chi2_ = new TH1F(XXname.c_str(),"", Nbins, low, up);
00052 }
00053   
00054 std::pair<unsigned,unsigned> SymmetryFit::findUsableMinMax() const
00055 {
00056   unsigned NEAR(0), FAR(0);
00057   const std::vector<std::pair<unsigned,unsigned> > cont = continuousRanges();
00058   for(unsigned L=0; L<cont.size(); L++) { if( cont[L].first > range_.first) continue;
00059     for(unsigned R=L; R<cont.size(); R++) { if( cont[R].second < range_.second) continue;
00060 
00061       const unsigned far = std::min( range_.first - cont[L].first,    
00062                                       cont[R].second - range_.second );
00063       const unsigned near = std::max( range_.second<cont[L].second ? 0 : range_.second - cont[L].second,  
00064                                      cont[R].first<range_.first ? 0 : cont[R].first - range_.first );
00065 
00066       if ( (far>near) && (far-near)>(FAR-NEAR) ) { FAR = far; NEAR = near;}
00067     }
00068   }
00069   return std::make_pair(NEAR,FAR);
00070 }
00071 
00072 std::vector<std::pair<unsigned,unsigned> > SymmetryFit::continuousRanges() const
00073 {
00074   std::vector<std::pair<unsigned,unsigned> > ranges;
00075   const unsigned Nbins = symm_candidate_->GetNbinsX();
00076   unsigned i=0;
00077   while(++i<=Nbins) {
00078     if(symm_candidate_->GetBinError(i)) {
00079       std::pair<unsigned,unsigned> range(i,i+1);
00080       while(++i<=Nbins && symm_candidate_->GetBinError(i)) range.second++;
00081       ranges.push_back(range);
00082     }
00083   }
00084   return ranges;
00085 }
00086 
00087 
00088 void SymmetryFit::fillchi2()
00089 {
00090   if(ndf_<minDF_) return;
00091 
00092   for(int i=1;  i<=chi2_->GetNbinsX() ; ++i) {
00093     const unsigned L( range_.first-1+(i-1)/2 ), R( range_.first+i/2 );
00094     chi2_->SetBinContent( i, chi2( std::make_pair(L,R)) );
00095   }
00096 }
00097 
00098 float SymmetryFit::chi2(std::pair<unsigned,unsigned> point)
00099 {
00100   point.first -= minmaxUsable_.first;
00101   point.second += minmaxUsable_.first;
00102   float XX=0;
00103   unsigned i=ndf_;
00104   while(i-->0) {
00105     XX += chi2_element(point); 
00106     point.first--; 
00107     point.second++;
00108   }
00109   return XX;
00110 }
00111 
00112 float SymmetryFit::chi2_element(std::pair<unsigned,unsigned> range)
00113 {
00114   float
00115     y0(symm_candidate_->GetBinContent(range.first)),
00116     y1(symm_candidate_->GetBinContent(range.second)),
00117     e0(symm_candidate_->GetBinError(range.first)),
00118     e1(symm_candidate_->GetBinError(range.second));           assert(e0&&e1);
00119 
00120   return pow(y0-y1, 2)/(e0*e0+e1*e1);
00121 }
00122 
00123 int SymmetryFit::fit() {
00124 
00125   std::vector<double> p = pol2_from_pol3(chi2_);
00126   if( !p.size() || 
00127       p[0] < chi2_->GetBinCenter(1) || 
00128       p[0] > chi2_->GetBinCenter(chi2_->GetNbinsX()))
00129     return 7;
00130 
00131   TF1* f = fitfunction();
00132   f->SetParameter(0, p[0]);  f->SetParLimits(0, p[0], p[0]);
00133   f->SetParameter(1, p[1]);  f->SetParLimits(1, p[1], p[1]);
00134   f->SetParameter(2, p[2]);  f->SetParLimits(2, p[2], p[2]);
00135   f->SetParameter(3, ndf_);  f->SetParLimits(3, ndf_,ndf_); //Fixed
00136   chi2_->Fit(f,"WQ");
00137   return 0;
00138 }
00139 
00140 TF1* SymmetryFit::fitfunction() 
00141 {
00142   TF1* f = new TF1("SymmetryFit","((x-[0])/[1])**2+[2]+0*[3]");
00143   f->SetParName(0,"middle");
00144   f->SetParName(1,"uncertainty");
00145   f->SetParName(2,"chi2");
00146   f->SetParName(3,"NDF");
00147   return f;
00148 }
00149 
00150 
00151 std::vector<double> SymmetryFit::pol2_from_pol2(TH1* hist) {
00152   std::vector<double> v;
00153 
00154   int status = hist->Fit("pol2","WQ");
00155   if(!status) {
00156     std::vector<double> p;
00157     p.push_back(hist->GetFunction("pol2")->GetParameter(0));
00158     p.push_back(hist->GetFunction("pol2")->GetParameter(1));
00159     p.push_back(hist->GetFunction("pol2")->GetParameter(2));
00160     if(p[2]>0) {
00161       v.push_back( -0.5*p[1]/p[2] );
00162       v.push_back( 1./sqrt(p[2]) );
00163       v.push_back( p[0]-0.25*p[1]*p[1]/p[2] );
00164     }
00165   }
00166   return v;
00167 }
00168 
00169 std::vector<double> SymmetryFit::pol2_from_pol3(TH1* hist) {
00170   std::vector<double> v;
00171 
00172   int status = hist->Fit("pol3","WQ");
00173   if(!status) {
00174     std::vector<double> p;
00175     p.push_back(hist->GetFunction("pol3")->GetParameter(0));
00176     p.push_back(hist->GetFunction("pol3")->GetParameter(1));
00177     p.push_back(hist->GetFunction("pol3")->GetParameter(2));
00178     p.push_back(hist->GetFunction("pol3")->GetParameter(3));
00179     double radical = p[2]*p[2] - 3*p[1]*p[3] ;
00180     if(radical>0) {
00181       double x0 = ( -p[2] + sqrt(radical) ) / ( 3*p[3] ) ;
00182       v.push_back( x0 );
00183       v.push_back( pow( radical, -0.25) );
00184       v.push_back( p[0] + p[1]*x0 + p[2]*x0*x0 + p[3]*x0*x0*x0 );
00185     }
00186   }
00187   return v;
00188 }