00001 #include "TemplateCreator.h"
00002 #include "RegisterModule.inc"
00003 #include "TGlobalData.h"
00004 #include "TSetupData.h"
00005 #include "ModulesOptions.h"
00006 #include "definitions.h"
00007 #include "EventNavigator.h"
00008 #include "SetupNavigator.h"
00009 #include "ExportPulse.h"
00010 #include "debug_tools.h"
00011
00012 #include "TH1D.h"
00013 #include "TMath.h"
00014
00015 #include <iostream>
00016 #include <sstream>
00017 #include <stdexcept>
00018 using std::cout;
00019 using std::endl;
00020
00021
00022 TemplateCreator::TemplateCreator(modules::options* opts):
00023 BaseModule("TemplateCreator",opts), fOpts(opts),
00024 fPulseDebug(false), fAnalyseAllChannels(false)
00025 {
00026 fRefineFactor = opts->GetInt("refine_factor", 5);
00027 fPulseDebug = opts->GetBool("pulse_debug", false);
00028 opts->GetVectorStringsByDelimiter("channels",fRequestedChannels);
00029 fArchiveName=opts->GetString("file_name","templates.root");
00030 if(fRequestedChannels.empty()) fAnalyseAllChannels=true;
00031
00032
00033 fCutIntegralRatio=opts->GetBool("use_IR_cut",false);
00034 if(fCutIntegralRatio){
00035 fIntegralMax=opts->GetDouble("max_integral");
00036 fIntegralMin=opts->GetDouble("min_integral");
00037 fIntegralRatioMax=opts->GetDouble("max_ratio");
00038 fIntegralRatioMin=opts->GetDouble("min_ratio");
00039 }
00040
00041 }
00042
00043 TemplateCreator::~TemplateCreator(){
00046 }
00047
00048 TemplateCreator::ChannelSet::ChannelSet(const std::string& det, const std::string& bank,
00049 modules::options* opts, int refine):
00050 detname(det), bankname(bank),
00051 fit_successes(0),fit_attempts(0),
00052 trigger_polarity(TSetupData::Instance()->GetTriggerPolarity(bank)),
00053 pulse_finder(NULL),
00054 integralRatio(new Algorithm::IntegralRatio(
00055 opts->GetInt("start_integral",10),
00056 opts->GetInt("start_tail",60),
00057 opts->GetInt("stop_integral",0),
00058 trigger_polarity))
00059 {
00060
00061 if(!opts->GetFlag("no_PCF_check")){
00062 pulse_finder = new PulseCandidateFinder(detname, opts);
00063 }
00064
00065
00066 fitter = new TemplateFitter(detname, refine);
00067
00068 template_pulse=new TTemplate(detname,refine,trigger_polarity,opts->GetFlag("debug"));
00069 }
00070
00071 void TemplateCreator::ChannelSet::Clear(){
00072 delete fitter;
00073 delete template_pulse;
00074 if(pulse_finder) delete pulse_finder;
00075 if(integralRatio) delete integralRatio;
00076 }
00077
00078
00079
00080
00081 int TemplateCreator::BeforeFirstEntry(TGlobalData* gData, const TSetupData* setup){
00082
00083
00084 if(fArchiveName==EventNavigator::Instance().GetOutputFileName()){
00085 fTemplateArchive = new TemplateArchive(GetDirectory());
00086 } else{
00087 fTemplateArchive = new TemplateArchive(fArchiveName.c_str(), "RECREATE");
00088 }
00089
00090
00091 StringPulseIslandMap::const_iterator it;
00092 for(it = gData->fPulseIslandToChannelMap.begin(); it != gData->fPulseIslandToChannelMap.end(); ++it){
00093 const std::string bankname = it->first;
00094 const std::string detname = TSetupData::Instance()->GetDetectorName(bankname);
00095 if(!fAnalyseAllChannels &&
00096 std::find(fRequestedChannels.begin(), fRequestedChannels.end(), detname)
00097 ==fRequestedChannels.end()) {
00098 continue;
00099 }
00100 if(Debug()) cout<<"TemplateCreator::BeforeFirstEntry: Will make template for '"<<detname<<"'"<<endl;
00101
00102 fChannels.push_back(ChannelSet(detname,bankname,fOpts,fRefineFactor));
00103 }
00104 return 0;
00105 }
00106
00107
00108
00109 int TemplateCreator::ProcessEntry(TGlobalData* gData, const TSetupData* setup){
00110
00111
00112 unsigned no_converged=0;
00113 for(ChannelList::iterator i_ch=fChannels.begin(); i_ch!=fChannels.end(); ++i_ch){
00114
00115
00116 if (i_ch->template_pulse->HasConverged()) {
00117 no_converged++;
00118 continue;
00119 }
00120
00121
00122 const std::string& bankname = i_ch->bankname;
00123 const std::string& detname = i_ch->detname;
00124 const PulseIslandList& thePulseIslands= gData->fPulseIslandToChannelMap.at(bankname);
00125 fTemplateFitter=i_ch->fitter;
00126
00127
00128 if (thePulseIslands.size() == 0) continue;
00129
00130
00131 for (PulseIslandList::const_iterator pulseIter = thePulseIslands.begin();
00132 pulseIter != thePulseIslands.end(); ++pulseIter) {
00133
00134 TPulseIsland* pulse = *pulseIter;
00135
00136 if(i_ch->pulse_finder){
00137
00138 i_ch->pulse_finder->FindPulseCandidates(pulse);
00139 int n_pulse_candidates = i_ch->pulse_finder->GetNPulseCandidates();
00140
00141
00142 if (n_pulse_candidates != 1) continue;
00143 }
00144
00145 if(fCutIntegralRatio){
00146 try{
00147 (*i_ch->integralRatio)(pulse);
00148 }catch(std::out_of_range& e){
00149 continue;
00150 }
00151 const double& integral=i_ch->integralRatio->GetTotal();
00152 const double& ratio=i_ch->integralRatio->GetRatio();
00153 if( fIntegralMax < integral || fIntegralMin > integral
00154 || fIntegralRatioMax < ratio || fIntegralRatioMin > ratio) {
00155 continue;
00156 }
00157 }
00158
00159
00160 int over_under_flow=HasPulseOverflowed(pulse,i_ch->bankname);
00161 if(over_under_flow!=0){
00162 if (Debug()) {
00163 cout << "TemplateCreator: Pulse #" << pulseIter - thePulseIslands.begin() << " has ";
00164 if(over_under_flow>0) cout << "overflowed";
00165 else cout<<"undeflowed";
00166 cout <<" the digitizer and won't be added to the template" << endl;
00167 }
00168 continue;
00169 }
00170
00171
00172 if (i_ch->template_pulse->Empty()) {
00173
00174 int pulseID=pulseIter- thePulseIslands.begin();
00175 TH1D* tpl=StartTemplate(pulseID, pulse,i_ch->detname);
00176 if(tpl) i_ch->template_pulse->Initialize(pulseID,tpl,GetDirectory());
00177 continue;
00178 }
00179
00180
00181
00182 TH1D* hPulseToFit = CreateRefinedPulseHistogram(pulse, "hPulseToFit", "hPulseToFit", false);
00183
00184
00185
00186 double template_amplitude = i_ch->template_pulse->GetAmplitude();
00187 double template_time = i_ch->template_pulse->GetTime();
00188
00189 double pulse_pedestal = hPulseToFit->GetBinContent(1);
00190 double pulse_amplitude = definitions::DefaultValue;
00191 double pulse_time = definitions::DefaultValue;
00192
00193
00194 double pedestal_offset_estimate = pulse_pedestal;
00195 double amplitude_scale_factor_estimate = definitions::DefaultValue;
00196 double time_offset_estimate = definitions::DefaultValue;
00197
00198
00199 if (TSetupData::Instance()->GetTriggerPolarity(bankname) >0) {
00200 pulse_amplitude = (hPulseToFit->GetMaximum() - pulse_pedestal);
00201 pulse_time = hPulseToFit->GetMaximumBin() - 1;
00202 }
00203 else if (TSetupData::Instance()->GetTriggerPolarity(bankname) <0) {
00204 pulse_amplitude = (pulse_pedestal - hPulseToFit->GetMinimum());
00205 pulse_time = hPulseToFit->GetMinimumBin() - 1;
00206 }
00207 amplitude_scale_factor_estimate = pulse_amplitude / template_amplitude;
00208 time_offset_estimate = pulse_time - template_time;
00209
00210 i_ch->fitter->SetInitialParameterEstimates(pedestal_offset_estimate, amplitude_scale_factor_estimate, time_offset_estimate);
00211
00212 int fit_status = i_ch->fitter->FitPulseToTemplate(i_ch->template_pulse, hPulseToFit, bankname);
00213 ++i_ch->fit_attempts;
00214 if (fit_status != 0) {
00215 if (Debug()) {
00216 std::cout << "TemplateCreator: Problem with fit (status = " << fit_status << ")" << std::endl;
00217 }
00218 delete hPulseToFit;
00219 continue;
00220 }
00221 ++i_ch->fit_successes;
00222
00223 if (Debug()) {
00224 cout << "Template Creator: Fitted Parameters: PedOffset = "
00225 << i_ch->fitter->GetPedestalOffset() << ", AmpScaleFactor = "
00226 << i_ch->fitter->GetAmplitudeScaleFactor() << ", TimeOffset = "
00227 << i_ch->fitter->GetTimeOffset() << ", Chi2 = "
00228 << i_ch->fitter->GetChi2() << ", NDoF = "
00229 << i_ch->fitter->GetNDoF() << ", Prob = "
00230 << TMath::Prob(i_ch->fitter->GetChi2(), i_ch->fitter->GetNDoF()) << std::endl << std::endl;
00231 }
00232
00233 if (fPulseDebug) {
00234
00235 if (i_ch->template_pulse->PulsesMerged() <= 10
00236 || ( i_ch->template_pulse->PulsesMerged() <= 100
00237 && i_ch->template_pulse->PulsesMerged()%10 == 0)
00238 || ( i_ch->template_pulse->PulsesMerged()%100 == 0) ) {
00239 std::stringstream newhistname;
00240 newhistname << "hTemplate_" << i_ch->template_pulse->PulsesMerged() << "Pulses_" << detname;
00241 i_ch->template_pulse->Clone(newhistname.str().c_str());
00242 }
00243 }
00244
00245
00246 i_ch->template_pulse->AddPulse(
00247 fTemplateFitter->GetTimeOffset(),
00248 fTemplateFitter->GetAmplitudeScaleFactor(),
00249 fTemplateFitter->GetPedestalOffset(),
00250 hPulseToFit);
00251
00252
00253 if (i_ch->template_pulse->CheckConverged()) {
00254 cout << "TemplateCreator: " << detname << " template terminated containing "
00255 << i_ch->template_pulse->PulsesMerged() <<" pulses "<< std::endl;
00256 break;
00257 }
00258 }
00259 }
00260
00261 if(no_converged==fChannels.size()){
00262 cout<<"All channels converged so end run"<<endl;
00263 return -1;
00264 }
00265
00266 return 0;
00267 }
00268
00269
00270
00271
00272 int TemplateCreator::AfterLastEntry(TGlobalData* gData, const TSetupData* setup){
00273
00274
00275 for(ChannelList::iterator i_ch=fChannels.begin(); i_ch!=fChannels.end(); ++i_ch){
00276
00277 if (i_ch->template_pulse->Empty()) {
00278 continue;
00279 }
00280
00281 cout << "TemplateCreator: " << i_ch->detname
00282 << ": " << i_ch->fit_attempts << " fits attempted with "
00283 << i_ch->fit_successes << " successful ("
00284 << ((double)i_ch->fit_successes/(double)i_ch->fit_attempts)*100 << "%)" << endl;
00285
00286
00287
00288 i_ch->template_pulse->AddToDirectory(GetDirectory("../"), GetDirectory());
00289
00290
00291 fTemplateArchive->SaveTemplate(i_ch->template_pulse);
00292
00293
00294 i_ch->Clear();
00295 }
00296
00297 return 0;
00298 }
00299
00300 int TemplateCreator::HasPulseOverflowed(const TPulseIsland* pulse, const std::string& bankname){
00301
00302 const std::vector<int>& theSamples = (pulse)->GetSamples();
00303 int n_samples = theSamples.size();
00304
00305
00306 int n_bits = TSetupData::Instance()->GetNBits(bankname);
00307 double max_adc_value = std::pow(2, n_bits);
00308
00309 for (int i = 0; i < n_samples; ++i) {
00310 int sample_value = theSamples.at(i);
00311 if (sample_value >= max_adc_value-1 && sample_value <= max_adc_value+1) {
00312 return 1;
00313 }
00314 else if (sample_value == 0) {
00315 return -1;
00316 }
00317 }
00318
00319 return 0;
00320 }
00321
00322 TH1D* TemplateCreator::StartTemplate(int pulseID, const TPulseIsland* pulse,const std::string& detname){
00323
00324
00325 int pulse_length = pulse->GetSamples().size();
00326 if (pulse->GetPeakSample() >= pulse_length - pulse_length/5.0) {
00327 if (Debug()) {
00328 cout << "TemplateCreator: Pulse #" << pulseID
00329 << " is too close to one end of the island and so won't be used as "
00330 "the first pulse in the template." << endl;
00331 }
00332 return NULL;
00333 }
00334 if (Debug()) {
00335 cout << "TemplateCreator: Adding " << detname << " Pulse #"
00336 << pulseID << " directly to the template" << endl;
00337 }
00338
00339 std::string histname = "hTemplate_" + detname;
00340 std::string histtitle = "Template Histogram for the " + detname + " channel";
00341 return CreateRefinedPulseHistogram(pulse, histname.c_str(), histtitle.c_str(), true);
00342 }
00343
00344
00345
00346
00347
00348 ALCAP_REGISTER_MODULE(TemplateCreator);