00001 #include "TemplateFitter.h"
00002
00003 #include "HistogramFitFCN.h"
00004 #include "SetupNavigator.h"
00005 #include "debug_tools.h"
00006
00007 #include "TMath.h"
00008
00009 TemplateFitter::TemplateFitter(std::string detname, int refine_factor): fChannel(detname), fRefineFactor(refine_factor) {
00010
00011 HistogramFitFCN* fcn = new HistogramFitFCN();
00012 fMinuitFitter = new TFitterMinuit(2);
00013 fMinuitFitter->SetMinuitFCN(fcn);
00014 fMinuitFitter->SetPrintLevel(-1);
00015 fcn->SetRefineFactor(fRefineFactor);
00016 }
00017
00018 TemplateFitter::~TemplateFitter() {
00019 }
00020
00021 int TemplateFitter::FitPulseToTemplate(const TTemplate* hTemplate, const TH1D* hPulse, const std::string& bankname){
00022
00023 int status;
00024 static int print_dbg = false;
00025
00026
00027
00028 int n_bits = TSetupData::Instance()->GetNBits(bankname);
00029 double max_adc_value = std::pow(2, n_bits);
00030
00031
00032
00033 fMinuitFitter->Clear();
00034 HistogramFitFCN* fcn = (HistogramFitFCN*)fMinuitFitter->GetMinuitFCN();
00035 fcn->SetTemplateHist(hTemplate->GetHisto(), hTemplate->GetPedestal());
00036 fcn->SetPulseHist(hPulse);
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 double max_time_offset = 10*fRefineFactor;
00047 double best_time_offset = 0;
00048 double best_pedestal_offset = 0;
00049 double best_amplitude_scale_factor = 0;
00050 double best_chi2 = 1e11;
00051 int best_status = -10000;
00052
00053
00054 fTimeOffset_minimum = fTimeOffset_estimate - max_time_offset;
00055 fTimeOffset_maximum = fTimeOffset_estimate + max_time_offset;
00056
00057 fPedestalOffset_minimum = 0;
00058 fPedestalOffset_maximum = max_adc_value;
00059
00060 fAmplitudeScaleFactor_minimum = 0.1;
00061 fAmplitudeScaleFactor_maximum = 1500;
00062
00063 for (double time_offset = fTimeOffset_minimum; time_offset <= fTimeOffset_maximum; ++time_offset) {
00064 if (print_dbg) {
00065 std::cout << "TemplateFitter: Checking time_offset = " << time_offset << std::endl;
00066 }
00067 fcn->SetTimeOffset(time_offset);
00068
00069
00070 fPedestalOffset = fPedestalOffset_estimate;
00071 fAmplitudeScaleFactor = fAmplitudeScaleFactor_estimate;
00072 fMinuitFitter->SetParameter(0, "PedestalOffset", fPedestalOffset, 0.1, fPedestalOffset_minimum, fPedestalOffset_maximum);
00073 fMinuitFitter->SetParameter(1, "AmplitudeScaleFactor", fAmplitudeScaleFactor, 0.1, fAmplitudeScaleFactor_minimum, fAmplitudeScaleFactor_maximum);
00074 fMinuitFitter->CreateMinimizer(TFitterMinuit::kMigrad);
00075
00076
00077
00078 status = fMinuitFitter->Minimize(1000);
00079
00080 if (status != 0){
00081 if (print_dbg){
00082 std::cout << "ERROR: Problem with fit (" << status << ")!" << std::endl;
00083 }
00084 continue;
00085 }
00086
00087
00088 fPedestalOffset = fMinuitFitter->GetParameter(0);
00089 fAmplitudeScaleFactor = fMinuitFitter->GetParameter(1);
00090
00091 double delta_ped_offset_error = 1;
00092 double delta_amp_sf_error = 0.001;
00093 if ( (fPedestalOffset < fPedestalOffset_minimum + delta_ped_offset_error
00094 && fPedestalOffset > fPedestalOffset_minimum - delta_ped_offset_error)
00095 || (fPedestalOffset < fPedestalOffset_maximum + delta_ped_offset_error
00096 && fPedestalOffset > fPedestalOffset_maximum - delta_ped_offset_error) ) {
00097 if (print_dbg) {
00098 std::cout << "ERROR: PedestalOffset has hit a boundary (" << fPedestalOffset << ")" << std::endl;
00099 }
00100 status = -9999;
00101 }
00102 else if ( (fAmplitudeScaleFactor < fAmplitudeScaleFactor_minimum + delta_amp_sf_error
00103 && fAmplitudeScaleFactor > fAmplitudeScaleFactor_minimum - delta_amp_sf_error)
00104 || (fAmplitudeScaleFactor < fAmplitudeScaleFactor_maximum + delta_amp_sf_error
00105 && fAmplitudeScaleFactor > fAmplitudeScaleFactor_maximum - delta_amp_sf_error) ) {
00106 if (print_dbg) {
00107 std::cout << "ERROR: AmplitudeScaleFactor has hit a boundary (" << fAmplitudeScaleFactor << ")" << std::endl;
00108 }
00109 status = -9999;
00110 }
00111
00112
00113
00114
00115 std::vector<double> params;
00116 params.push_back(fPedestalOffset);
00117 params.push_back(fAmplitudeScaleFactor);
00118
00119 fChi2 = (*fcn)(params);
00120
00121 fNDoF = fcn->GetNDoF();
00122
00123 if (status == 0 && fChi2 < best_chi2) {
00124 best_time_offset = time_offset;
00125 best_pedestal_offset = fPedestalOffset;
00126 best_amplitude_scale_factor = fAmplitudeScaleFactor;
00127 best_chi2 = fChi2;
00128 best_status = status;
00129 }
00130
00131 if (print_dbg) {
00132 std::cout << "TemplateFitter::FitPulseToTemplate(): Fit:\tChi2 " << fChi2 << "\tP "
00133 << fPedestalOffset << "\tA " << fAmplitudeScaleFactor << "\tT " << fTimeOffset
00134 << ", ndof = " << fNDoF << ", prob = " << TMath::Prob(fChi2, fNDoF) << std::endl;
00135 }
00136 }
00137
00138
00139 fChi2 = best_chi2;
00140 fTimeOffset = best_time_offset;
00141 fPedestalOffset = best_pedestal_offset;
00142 fAmplitudeScaleFactor = best_amplitude_scale_factor;
00143
00144 double delta_time_offset_error = 1;
00145 if ( (fTimeOffset < fTimeOffset_minimum + delta_time_offset_error && fTimeOffset > fTimeOffset_minimum - delta_time_offset_error) ||
00146 (fTimeOffset < fTimeOffset_maximum + delta_time_offset_error && fTimeOffset > fTimeOffset_maximum - delta_time_offset_error) ) {
00147
00148 if (print_dbg) {
00149 std::cout << "ERROR: TimeOffset has hit a boundary (" << fTimeOffset << ")" << std::endl;
00150 }
00151 best_status = -9999;
00152 }
00153
00154 return best_status;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 void TemplateFitter::SetInitialParameterEstimates(double pedestal, double amplitude, double time) {
00170 fPedestalOffset_estimate = pedestal;
00171 fAmplitudeScaleFactor_estimate = amplitude;
00172 fTimeOffset_estimate = time;
00173 }