00001 #include "Alignment/MuonAlignmentAlgorithms/interface/MuonResiduals1DOFFitter.h"
00002 #include "TMath.h"
00003
00004 static TMinuit *MuonResiduals1DOFFitter_TMinuit;
00005 static double MuonResiduals1DOFFitter_sum_of_weights;
00006 static double MuonResiduals1DOFFitter_number_of_hits;
00007 static bool MuonResiduals1DOFFitter_weightAlignment;
00008
00009 void MuonResiduals1DOFFitter::inform(TMinuit *tMinuit) {
00010 MuonResiduals1DOFFitter_TMinuit = tMinuit;
00011 }
00012
00013 void MuonResiduals1DOFFitter_FCN(int &npar, double *gin, double &fval, double *par, int iflag) {
00014 MuonResidualsFitterFitInfo *fitinfo = (MuonResidualsFitterFitInfo*)(MuonResiduals1DOFFitter_TMinuit->GetObjectFit());
00015 MuonResidualsFitter *fitter = fitinfo->fitter();
00016
00017 fval = 0.;
00018 for (std::vector<double*>::const_iterator resiter = fitter->residuals_begin(); resiter != fitter->residuals_end(); ++resiter) {
00019 const double residual = (*resiter)[MuonResiduals1DOFFitter::kResid];
00020 const double redchi2 = (*resiter)[MuonResiduals1DOFFitter::kRedChi2];
00021
00022 const double residpeak = par[MuonResiduals1DOFFitter::kAlign];
00023 const double residsigma = par[MuonResiduals1DOFFitter::kSigma];
00024 const double residgamma = par[MuonResiduals1DOFFitter::kGamma];
00025
00026 double weight = (1./redchi2) * MuonResiduals1DOFFitter_number_of_hits / MuonResiduals1DOFFitter_sum_of_weights;
00027 if (!MuonResiduals1DOFFitter_weightAlignment) weight = 1.;
00028
00029 if (!MuonResiduals1DOFFitter_weightAlignment || TMath::Prob(redchi2*8, 8) < 0.99) {
00030 if (fitter->residualsModel() == MuonResidualsFitter::kPureGaussian) {
00031 fval += -weight * MuonResidualsFitter_logPureGaussian(residual, residpeak, residsigma);
00032 }
00033 else if (fitter->residualsModel() == MuonResidualsFitter::kPowerLawTails) {
00034 fval += -weight * MuonResidualsFitter_logPowerLawTails(residual, residpeak, residsigma, residgamma);
00035 }
00036 else if (fitter->residualsModel() == MuonResidualsFitter::kROOTVoigt) {
00037 fval += -weight * MuonResidualsFitter_logROOTVoigt(residual, residpeak, residsigma, residgamma);
00038 }
00039 else if (fitter->residualsModel() == MuonResidualsFitter::kGaussPowerTails) {
00040 fval += -weight * MuonResidualsFitter_logGaussPowerTails(residual, residpeak, residsigma);
00041 }
00042 else { assert(false); }
00043
00044 }
00045 }
00046 }
00047
00048 double MuonResiduals1DOFFitter::sumofweights() {
00049 MuonResiduals1DOFFitter_sum_of_weights = 0.;
00050 MuonResiduals1DOFFitter_number_of_hits = 0.;
00051 MuonResiduals1DOFFitter_weightAlignment = m_weightAlignment;
00052 for (std::vector<double*>::const_iterator resiter = residuals_begin(); resiter != residuals_end(); ++resiter) {
00053 if (m_weightAlignment) {
00054 double redchi2 = (*resiter)[MuonResiduals1DOFFitter::kRedChi2];
00055 if (TMath::Prob(redchi2*8, 8) < 0.99) {
00056 MuonResiduals1DOFFitter_sum_of_weights += 1./redchi2;
00057 MuonResiduals1DOFFitter_number_of_hits += 1.;
00058 }
00059 }
00060 else {
00061 MuonResiduals1DOFFitter_sum_of_weights += 1.;
00062 MuonResiduals1DOFFitter_number_of_hits += 1.;
00063 }
00064 }
00065 return MuonResiduals1DOFFitter_sum_of_weights;
00066 }
00067
00068 bool MuonResiduals1DOFFitter::fit(Alignable *ali) {
00069 initialize_table();
00070 sumofweights();
00071
00072 double resid_sum = 0.;
00073 double resid_sum2 = 0.;
00074 double resid_N = 0.;
00075 int N = 0;
00076
00077 for (std::vector<double*>::const_iterator resiter = residuals_begin(); resiter != residuals_end(); ++resiter) {
00078 const double residual = (*resiter)[MuonResiduals1DOFFitter::kResid];
00079 const double redchi2 = (*resiter)[MuonResiduals1DOFFitter::kRedChi2];
00080 double weight = 1./redchi2;
00081 if (!m_weightAlignment) weight = 1.;
00082
00083 if (!m_weightAlignment || TMath::Prob(redchi2*8, 8) < 0.99) {
00084 if (fabs(residual) < 10.) {
00085 resid_sum += weight * residual;
00086 resid_sum2 += weight * residual * residual;
00087 resid_N += weight;
00088 N++;
00089 }
00090 }
00091 }
00092
00093 double resid_mean = resid_sum/resid_N;
00094 double resid_stdev = sqrt(resid_sum2/resid_N - pow(resid_sum/resid_N, 2));
00095
00096 resid_sum = 0.;
00097 resid_sum2 = 0.;
00098 resid_N = 0.;
00099
00100 for (std::vector<double*>::const_iterator resiter = residuals_begin(); resiter != residuals_end(); ++resiter) {
00101 const double residual = (*resiter)[MuonResiduals1DOFFitter::kResid];
00102 const double redchi2 = (*resiter)[MuonResiduals1DOFFitter::kRedChi2];
00103 double weight = 1./redchi2;
00104 if (!m_weightAlignment) weight = 1.;
00105
00106 if (!m_weightAlignment || TMath::Prob(redchi2*8, 8) < 0.99) {
00107 if (fabs(residual - resid_mean) < 2.5*resid_stdev) {
00108 resid_sum += weight * residual;
00109 resid_sum2 += weight * residual * residual;
00110 resid_N += weight;
00111 }
00112 }
00113 }
00114
00115 resid_mean = resid_sum/resid_N;
00116 resid_stdev = sqrt(resid_sum2/resid_N - pow(resid_sum/resid_N, 2));
00117
00118 std::vector<int> num;
00119 std::vector<std::string> name;
00120 std::vector<double> start;
00121 std::vector<double> step;
00122 std::vector<double> low;
00123 std::vector<double> high;
00124
00125 if (fixed(kAlign)) {
00126 num.push_back(kAlign); name.push_back(std::string("Align")); start.push_back(0.); step.push_back(0.01*resid_stdev); low.push_back(0.); high.push_back(0.);
00127 } else {
00128 num.push_back(kAlign); name.push_back(std::string("Align")); start.push_back(resid_mean); step.push_back(0.01*resid_stdev); low.push_back(0.); high.push_back(0.);
00129 }
00130 num.push_back(kSigma); name.push_back(std::string("Sigma")); start.push_back(resid_stdev); step.push_back(0.01*resid_stdev); low.push_back(0.); high.push_back(0.);
00131 if (residualsModel() != kPureGaussian && residualsModel() != kGaussPowerTails) {
00132 num.push_back(kGamma); name.push_back(std::string("Gamma")); start.push_back(0.1*resid_stdev); step.push_back(0.01*resid_stdev); low.push_back(0.); high.push_back(0.);
00133 }
00134
00135 return dofit(&MuonResiduals1DOFFitter_FCN, num, name, start, step, low, high);
00136 }
00137
00138 double MuonResiduals1DOFFitter::plot(std::string name, TFileDirectory *dir, Alignable *ali) {
00139 sumofweights();
00140
00141 std::stringstream name_residual, name_residual_raw;
00142 name_residual << name << "_residual";
00143 name_residual_raw << name << "_residual_raw";
00144
00145 double min_residual = -100.; double max_residual = 100.;
00146 TH1F *hist_residual = dir->make<TH1F>(name_residual.str().c_str(), "", 100, min_residual, max_residual);
00147 TH1F *hist_residual_raw = dir->make<TH1F>(name_residual_raw.str().c_str(), "", 100, min_residual, max_residual);
00148
00149 name_residual << "_fit";
00150 TF1 *fit_residual = NULL;
00151 if (residualsModel() == kPureGaussian) {
00152 fit_residual = new TF1(name_residual.str().c_str(), MuonResidualsFitter_pureGaussian_TF1, min_residual, max_residual, 3);
00153 fit_residual->SetParameters(MuonResiduals1DOFFitter_sum_of_weights * (max_residual - min_residual)/100., 10.*value(kAlign), 10.*value(kSigma));
00154 }
00155 else if (residualsModel() == kPowerLawTails) {
00156 fit_residual = new TF1(name_residual.str().c_str(), MuonResidualsFitter_powerLawTails_TF1, min_residual, max_residual, 4);
00157 fit_residual->SetParameters(MuonResiduals1DOFFitter_sum_of_weights * (max_residual - min_residual)/100., 10.*value(kAlign), 10.*value(kSigma), 10.*value(kGamma));
00158 }
00159 else if (residualsModel() == kROOTVoigt) {
00160 fit_residual = new TF1(name_residual.str().c_str(), MuonResidualsFitter_ROOTVoigt_TF1, min_residual, max_residual, 4);
00161 fit_residual->SetParameters(MuonResiduals1DOFFitter_sum_of_weights * (max_residual - min_residual)/100., 10.*value(kAlign), 10.*value(kSigma), 10.*value(kGamma));
00162 }
00163 else if (residualsModel() == kGaussPowerTails) {
00164 fit_residual = new TF1(name_residual.str().c_str(), MuonResidualsFitter_GaussPowerTails_TF1, min_residual, max_residual, 3);
00165 fit_residual->SetParameters(MuonResiduals1DOFFitter_sum_of_weights * (max_residual - min_residual)/100., 10.*value(kAlign), 10.*value(kSigma));
00166 }
00167 else { assert(false); }
00168
00169 fit_residual->SetLineColor(2); fit_residual->SetLineWidth(2);
00170 fit_residual->Write();
00171
00172 for (std::vector<double*>::const_iterator resiter = residuals_begin(); resiter != residuals_end(); ++resiter) {
00173 const double resid = (*resiter)[MuonResiduals1DOFFitter::kResid];
00174 const double redchi2 = (*resiter)[MuonResiduals1DOFFitter::kRedChi2];
00175 double weight = 1./redchi2;
00176 if (!m_weightAlignment) weight = 1.;
00177
00178 if (!m_weightAlignment || TMath::Prob(redchi2*8, 8) < 0.99) {
00179 hist_residual->Fill(10.*(resid + value(kAlign)), weight);
00180 }
00181
00182 hist_residual_raw->Fill(10.*resid);
00183 }
00184
00185 double chi2 = 0.;
00186 double ndof = 0.;
00187 for (int i = 1; i <= hist_residual->GetNbinsX(); i++) {
00188 double xi = hist_residual->GetBinCenter(i);
00189 double yi = hist_residual->GetBinContent(i);
00190 double yerri = hist_residual->GetBinError(i);
00191 double yth = fit_residual->Eval(xi);
00192 if (yerri > 0.) {
00193 chi2 += pow((yth - yi)/yerri, 2);
00194 ndof += 1.;
00195 }
00196 }
00197 ndof -= npar();
00198
00199 return (ndof > 0. ? chi2 / ndof : -1.);
00200 }