00001 #include "TTemplate.h"
00002 #include "debug_tools.h"
00003
00004 #include <cmath>
00005 #include <iostream>
00006 using std::cout;
00007 using std::endl;
00008
00009 TTemplate::TTemplate():
00010 fDebug(false),
00011 fConverged(false),
00012 fTotalPulses(0),
00013 fRefineFactor(0),
00014 fTriggerPolarity(0),
00015 fChannel(),
00016 fErrors(NULL),
00017 fTemplatePulse(NULL){
00018 }
00019
00020 TTemplate::TTemplate(const std::string& det,int refine,int trigger_polarity, bool debug):
00021 fDebug(debug),
00022 fConverged(false),
00023 fTotalPulses(0),
00024 fRefineFactor(refine),
00025 fTriggerPolarity(trigger_polarity),
00026 fChannel(det),
00027 fName(MakeName(fChannel)),
00028 fTemplatePulse(NULL){
00029
00030
00031 std::string error_histname = "hErrorVsPulseAdded_" + fChannel.str();
00032 std::string error_histtitle = "Plot of the Error as each new Pulse is added to the template for the " + fChannel.str() + " channel";
00033 int n_bins = 10000;
00034 fErrors = new TH1D(error_histname.c_str(), error_histtitle.c_str(), n_bins,0,n_bins);
00035 }
00036
00037 TTemplate::~TTemplate(){
00038 }
00039
00040 void TTemplate::Initialize(int pulseID, TH1D* pulse, TDirectory* dir){
00041
00042 fTemplatePulse=pulse;
00043 fTemplatePulse->SetBit(TH1::kIsAverage);
00044 ++fTotalPulses;
00045 }
00046
00047 void TTemplate::AddPulse(double x_offset, double y_scale, double y_offset, const TH1D* hPulse){
00048
00049 if (fDebug) {
00050 std::cout << "TTemplate::AddPulse(): # pulses = " << fTotalPulses << std::endl;
00051 }
00052
00053 double template_pedestal = fTemplatePulse->GetBinContent(1);
00054 double total_error=0;
00055
00056
00057 for (int iPulseBin = 1; iPulseBin < hPulse->GetNbinsX(); ++iPulseBin) {
00058
00059
00060 double uncorrected_value = hPulse->GetBinContent(iPulseBin);
00061 double corrected_value = uncorrected_value - y_offset;
00062 corrected_value /= y_scale;
00063 corrected_value += template_pedestal;
00064
00065
00066
00067
00068 int bin_number = iPulseBin + 0.5 - x_offset;
00069
00070
00071 if (bin_number < 1 || bin_number > fTemplatePulse->GetNbinsX()) {
00072 continue;
00073 }
00074
00075
00076 double old_bin_content = fTemplatePulse->GetBinContent(bin_number);
00077 double old_bin_error = fTemplatePulse->GetBinError(bin_number);
00078
00079
00080 double new_bin_content = fTotalPulses * old_bin_content + corrected_value;
00081 new_bin_content /= (fTotalPulses + 1);
00082
00084 double new_bin_error = ((fTotalPulses - 1)*old_bin_error*old_bin_error)
00085 + (corrected_value - old_bin_content)*(corrected_value - new_bin_content);
00086 new_bin_error = std::sqrt(new_bin_error / fTotalPulses);
00087
00088
00089 total_error+=new_bin_error;
00090
00091 if (fDebug) {
00092 cout << "TemplateCreator::AddPulseToTemplate(): Bin #" << bin_number
00093 << ": Corrected Sample Value = " << corrected_value << endl
00094 << "\t\t\tOld Value (Error) = " << old_bin_content << "(" << old_bin_error << ")" << endl
00095 << "\t\t\tNew Value (Error) = " << new_bin_content << "(" << new_bin_error << ")" << endl;
00096 }
00097
00098
00099 fTemplatePulse->SetBinContent(bin_number, new_bin_content);
00100 fTemplatePulse->SetBinError(bin_number, new_bin_error);
00101 }
00102
00103
00104 ++fTotalPulses;
00105
00106
00107 fErrors->Fill(fTotalPulses, total_error);
00108 }
00109
00110 bool TTemplate::CheckConverged(){
00111 if(fConverged) return true;
00112
00113
00114 int n_bins_to_check = 10;
00115 if (fTotalPulses<n_bins_to_check) return false;
00116 double convergence_limit = 0.1;
00117 int newest_bin=fErrors->FindBin(fTotalPulses);
00118 double error=fErrors->GetBinContent(newest_bin)/fTotalPulses;
00119 for (int iPrevBin = 0; iPrevBin < n_bins_to_check; ++iPrevBin) {
00120 double previous_error = fErrors->GetBinContent(newest_bin-iPrevBin);
00121 previous_error /= fTotalPulses- iPrevBin;
00122
00123 if ( std::fabs(previous_error - error) > convergence_limit) {
00124 fConverged=false;
00125 break;
00126 } else{
00127 fConverged=true;
00128 }
00129 }
00130
00131 return fConverged;
00132 }
00133
00134 void TTemplate::NormaliseToAmplitude(){
00135 if(!fTemplatePulse) return;
00136 fTemplatePulse->SetBit(TH1::kIsAverage);
00137 SubtractPedestal();
00138
00139 double norm = std::fabs(fTemplatePulse->GetMaximum());
00140 ScaleHist(1./norm);
00141 }
00142
00143 void TTemplate::NormaliseToIntegral(){
00144 if(!fTemplatePulse) return;
00145 fTemplatePulse->SetBit(TH1::kIsAverage);
00146 SubtractPedestal();
00147
00148 double norm = fTemplatePulse->Integral();
00149 ScaleHist(1./norm);
00150 }
00151
00152 void TTemplate::NormaliseToSumSquares(){
00153 if(!fTemplatePulse) return;
00154 fTemplatePulse->SetBit(TH1::kIsAverage);
00155 SubtractPedestal();
00156
00157 TH1D* tmp = (TH1D*) fTemplatePulse->Clone("tmp");
00158 tmp->Multiply(tmp);
00159 double norm = sqrt(tmp->Integral());
00160 delete tmp;
00161 ScaleHist(1./norm);
00162 }
00163
00164 TH1* TTemplate::RebinToOriginalSampling(){
00165 return fTemplatePulse->Rebin(fRefineFactor);
00166 }
00167
00168 void TTemplate::SubtractPedestal(){
00169
00170
00171
00172 int n_bins_for_template_pedestal = 5;
00173 double total = 0;
00174 for (int iBin = 1; iBin <= n_bins_for_template_pedestal; ++iBin) {
00175 total += fTemplatePulse->GetBinContent(iBin);
00176 }
00177 double template_pedestal = total / n_bins_for_template_pedestal;
00178
00179
00180 for (int iBin = 1; iBin <= fTemplatePulse->GetNbinsX(); ++iBin) {
00181 double old_value = fTemplatePulse->GetBinContent(iBin);
00182 double new_value = old_value - template_pedestal;
00183
00184 fTemplatePulse->SetBinContent(iBin, new_value);
00185 }
00186 }
00187
00188 void TTemplate::ScaleHist(double factor){
00189
00190
00191 for (int iBin = 0; iBin <= fTemplatePulse->GetNbinsX(); ++iBin) {
00192 double old_value = fTemplatePulse->GetBinContent(iBin);
00193 double new_value = old_value * factor;
00194
00195 fTemplatePulse->SetBinContent(iBin, new_value);
00196 }
00197 }
00198
00199
00200 double TTemplate::GetPedestal()const{
00201 return fTemplatePulse->GetBinContent(1);
00202 }
00203
00204 double TTemplate::GetTime()const{
00205 if(fTriggerPolarity>0) return fTemplatePulse->GetMaximumBin()-1;
00206 return fTemplatePulse->GetMinimumBin()-1;
00207 }
00208
00209 double TTemplate::GetAmplitude()const{
00210 if(fTriggerPolarity>0) return fTemplatePulse->GetMaximum() - GetPedestal();
00211 return GetPedestal() - fTemplatePulse->GetMinimum();
00212 }