AverageWaveforms.cc

00001 #include "AverageWaveforms.hh"
00002 #include "ConvertData.hh"
00003 #include "BaselineFinder.hh"
00004 #include "SumChannels.hh"
00005 #include "intarray.hh"
00006 #include "TGraphErrors.h"
00007 #include "TFile.h"
00008 #include "PulseFinder.hh"
00009 #include "RootWriter.hh"
00010 #include "EventData.hh"
00011 
00012 #include <algorithm>
00013 #include <functional>
00014 #include <iostream>
00015 #include <fstream>
00016 #include <string>
00017 #include <sstream>
00018 using namespace std;
00019 
00020 AverageWaveforms::AverageWaveforms() : 
00021     BaseModule(GetDefaultName(), "Average the waveform for each channel over the entire run and save to the output root file")
00022 {
00023     AddDependency<ConvertData>();
00024     AddDependency<SumChannels>();
00025     AddDependency<BaselineFinder>();
00026     AddDependency<PulseFinder>();
00027     //AddDependency<RootWriter>();
00028 
00029     //Register all the config handler parameters
00030     RegisterParameter("use_event_list", use_event_list = false, 
00031                       "True if no cuts should be performed and the average should be constructed from a set of events specified in a text file.");
00032     RegisterParameter("event_list_location", event_list_location = "auxiliary_files/average_event_list.txt", 
00033                       "Location of text file to be used if use_event_list is true. Each line of the file must have the run number and then the event number (separated by a space) sorted in ascending order.");
00034 
00035     //Register all the cut parameters. These are ignored if use_event_list is set to true.
00036     RegisterParameter("with_s2", with_s2 = false, "True if run contains s2");
00037     RegisterParameter("min_pulse_height", min_pulse_height = 100,
00038                       "Minimum pulse height for one waveform to be counted in average waveform");
00039     RegisterParameter("max_pulse_height", max_pulse_height = 3000,
00040                       "Maximum pulse height for one waveform to be counted in average waveform");
00041     RegisterParameter("min_fprompt", min_fprompt = 0,
00042                       "Minimum fprompt for one waveform to be counted in average waveform");
00043     RegisterParameter("max_fprompt", max_fprompt = 1,
00044                       "Maximum fprompt for one waveform to be counted in average waveform");
00045     RegisterParameter("align_by_peak", align_by_peak = true,
00046                       "Align waveforms by the peak of the first pulse on the sum channel. Otherwise align by the trigger.");
00047     RegisterParameter("sum_start_time", sum_start_time = -20,
00048                       "");
00049     RegisterParameter("sum_end_time", sum_end_time = 400,
00050                       "");
00051     RegisterParameter("min_s1_start_time", min_s1_start_time = -0.08,
00052                       "");
00053     RegisterParameter("max_s1_start_time", max_s1_start_time = 0.05,
00054                       "");
00055     RegisterParameter("bin_size", bin_size = 50, "Use multiple of baseline group #");
00056     RegisterParameter("min_s2_start_time", min_s2_start_time = 40, "");
00057     RegisterParameter("max_s2_start_time", max_s2_start_time = 300, "");
00058     RegisterParameter("number_of_base_groups", number_of_base_groups = 2, "");
00059 }
00060 
00061 AverageWaveforms::~AverageWaveforms()
00062 {
00063     Cleanup();
00064 }
00065 
00066 void AverageWaveforms::Cleanup()
00067 {
00068     std::map<int,TGraphErrors*>::iterator mapit = _plots.begin();
00069     for( ; mapit != _plots.end() ; mapit++){
00070         delete mapit->second;
00071     }
00072     _plots.clear();
00073     _num_event.clear();
00074 }
00075 
00076 
00077 int AverageWaveforms::Initialize()
00078 { 
00079     // opens file stream, takes first event
00080     if (use_event_list)
00081     {
00082         string line;
00083         current_event = -1;
00084         current_run = -1;
00085         txt.open(event_list_location.c_str());
00086         if (txt.is_open() && txt.good())
00087         {
00088             getline(txt,line);
00089             istringstream ss1(line);
00090             string temp;
00091             getline(ss1, temp, ' ');
00092             istringstream ss2(temp);
00093             ss2 >> current_run;
00094             getline(ss1, temp, ' ');
00095             istringstream ss3(temp);
00096             ss3 >> current_event;
00097         }
00098     }
00099     return 0; 
00100 }
00101 
00102 int AverageWaveforms::Finalize()
00103 {
00104     if(gFile && gFile->IsOpen()){
00105         std::map<int,TGraphErrors*>::iterator mapit = _plots.begin();
00106         for( ; mapit != _plots.end(); mapit++){
00107             TGraphErrors* graph = mapit->second;
00108             //double* y = graph->GetY();
00109             double* ey = graph->GetEY();
00110 
00111             for(int i=0; i < graph->GetN(); i++){
00112                 // ey stored sum of variances
00113                 ey[i] = sqrt(ey[i]);
00114             }
00115             graph->SetFillStyle(3002);
00116             graph->SetFillColor(kRed);
00117             graph->Write();
00118         }
00119     }
00120     std::map<int, int>::iterator numOfEvents = _num_event.begin();
00121     for ( ; numOfEvents != _num_event.end(); numOfEvents++){
00122         Message(INFO)<<"<Module> AverageWaveforms: Channel "<< numOfEvents->first
00123                      <<" includes "<< numOfEvents->second <<" events"<<std::endl;
00124     }
00125     if (txt.is_open())
00126         txt.close();
00127     Cleanup();
00128     return 0;
00129 }
00130 
00131 int AverageWaveforms::Process(EventPtr evt)
00132 {
00133     EventDataPtr event = evt->GetEventData();
00134     ChannelData* sum_ch = event->GetChannelByID(ChannelData::CH_SUM);
00135 
00136     //Event level cuts
00137     if (align_by_peak && !sum_ch)
00138         return 0;
00139 
00140     if (!use_event_list)
00141     {   
00142         if (!sum_ch)
00143             return 0;
00144 
00145         if(! with_s2)
00146         {
00147             // look only at events with 1 scintillation pulse
00148             if (sum_ch->pulses.size() != 1) 
00149                 return 0;
00150         }
00151         else
00152         { //with s2
00153           // look only at events with 2 scintillation pulse
00154             if (sum_ch->pulses.size()!=2) 
00155                 return 0;
00156             // s2 starts at required region
00157             if (sum_ch->pulses[1].start_time < min_s2_start_time) 
00158                 return 0;
00159             if (sum_ch->pulses[1].start_time > max_s2_start_time) 
00160                 return 0;
00161         }
00162 
00163         // s1 starts at required region
00164         if (sum_ch->pulses[0].start_time < min_s1_start_time) return 0;
00165         if (sum_ch->pulses[0].start_time > max_s1_start_time) return 0;
00166         if (sum_ch->pulses[0].f90 < min_fprompt) return 0;
00167         if (sum_ch->pulses[0].f90 > max_fprompt) return 0;
00168     }
00169 
00170     else
00171     {//Select only events that appear in event list
00172       
00173         // Move to the correct run number
00174         while (event->run_id != current_run && txt.is_open() && txt.good())
00175         {
00176             string line;
00177             getline(txt,line);
00178             istringstream ss1(line);
00179             string temp;
00180             getline(ss1, temp, ' ');
00181             istringstream ss2(temp);
00182             ss2 >> current_run;
00183             getline(ss1, temp, ' ');
00184             istringstream ss3(temp);
00185             ss3 >> current_event;
00186         }
00187       
00188         // Check for event in text file
00189         if (event->event_id != current_event)
00190             return 0;
00191     }
00192   
00193     
00194     //Loop over individual channels
00195     for (size_t ch = 0; ch < event->channels.size(); ch++)
00196     {
00197         ChannelData& chdata = event->channels[ch];
00198         //skip channels we've been told to explicitly skip
00199         if(_skip_channels.find(chdata.channel_id) != _skip_channels.end())
00200             continue;
00201 
00202         //Channel level cuts
00203         if (!use_event_list)
00204         {   
00205             // baseline must have been found
00206             if(!(chdata.baseline.found_baseline) || chdata.baseline.saturated) 
00207                 continue;
00208             // saturation cut
00209             if (chdata.saturated)
00210                 continue;
00211         }
00212         // end of cuts
00213 
00214       //debug
00215       //Message(INFO) << "Processing run: " << event->run_id << " Event: " << event->event_id <<" Channel: "<<ch<<endl;
00216 
00217         _num_event[chdata.channel_id]++;
00218         const double* wave = chdata.GetBaselineSubtractedWaveform();
00219         int start_samp; 
00220         int end_samp; 
00221         if (align_by_peak == true)
00222         {
00223             double sum_peak_time = sum_ch->pulses[0].peak_time;
00224             start_samp = chdata.TimeToSample(sum_start_time - sum_peak_time, true);
00225             end_samp = chdata.TimeToSample(sum_end_time - sum_peak_time, true);
00226         }
00227         else
00228         {
00229             start_samp = chdata.TimeToSample(sum_start_time, true);
00230             end_samp = chdata.TimeToSample(sum_end_time, true);
00231         }
00232         const int nsamps = (end_samp - start_samp + 1) / bin_size;
00233 
00234         std::map<int,TGraphErrors*>::iterator prev = _plots.find(chdata.channel_id); 
00235         if(prev == _plots.end())
00236         { // first event
00237             double* x_ray = new double[nsamps];
00238             double* y_ray = new double[nsamps];
00239             double* ey_ray = new double[nsamps];
00240             TGraphErrors* avg = new TGraphErrors(nsamps, x_ray, y_ray, 0, ey_ray);
00241             char name[25];
00242             sprintf(name,"average_channel%d",chdata.channel_id);
00243             avg->SetName(name);
00244             avg->SetTitle(name);
00245     
00246             double* x = avg->GetX();
00247             double* y = avg->GetY();
00248             double* ey = avg->GetEY();
00249             int index;
00250             double yj;
00251             int j;
00252             //Loop over samples in average waveform
00253             for(int i=0; i < nsamps; i++)
00254             {
00255                 index = start_samp+i*bin_size;
00256                 yj = 0;
00257                 x[i]=chdata.SampleToTime(index);
00258                 y[i]=0;
00259                 ey[i]=0;
00260                 //Loop over corresponding samples in channel waveform (possibly finer binning than average waveform)
00261                 for (j=0; j<bin_size; j++)
00262                 {
00263                     if (chdata.channel_id >= 0)
00264                         yj = yj - wave[index+j]/(chdata.spe_mean);
00265                     else
00266                         yj = yj - wave[index+j];
00267                 }
00268                 y[i] += yj;
00269 
00270                 // Add variances, taking overall sqrt when finalize 
00271                 ey[i] = fabs(y[i]); //*pow(chdata.spe_sigma/chdata.spe_mean,2);
00272             }
00273             _plots.insert(std::make_pair(chdata.channel_id,avg));
00274         }
00275         else
00276         {
00277             TGraphErrors* avg = prev->second;
00278             if(avg->GetN() != nsamps)
00279             {
00280                 Message(ERROR)<<"Uneven number of samples between two events "
00281                               <<"for channel "<<chdata.channel_id<<std::endl;
00282                 return 1;
00283             }
00284     
00285             double* y = avg->GetY();
00286             double* ey = avg->GetEY();
00287             int index;
00288             double yj;
00289             int j;
00290             //Loop over samples in average waveform
00291             for(int i=0; i < nsamps; i++)
00292             {
00293                 index = start_samp+i*bin_size;
00294                 yj=0;
00295                 //Loop over corresponding samples in channel waveform (possibly finer binning than average waveform)
00296                 for (j=0; j<bin_size; j++)
00297                 {
00298                    if (chdata.channel_id >= 0)
00299                         yj = yj - wave[index+j]/(chdata.spe_mean);
00300                     else
00301                         yj = yj - wave[index+j];
00302                 }
00303                 y[i] += yj;
00304 
00305                 // Add variances, taking overall sqrt when finalize 
00306                 ey[i] += fabs(yj); //*pow(chdata.spe_sigma/chdata.spe_mean,2);;
00307             }
00308         }
00309     }
00310 
00311     // move to next event in the event list
00312     if (use_event_list && txt.is_open() && txt.good())
00313     {
00314         string line;
00315         getline(txt,line);
00316         istringstream ss1(line);
00317         string temp;
00318         getline(ss1, temp, ' ');
00319         istringstream ss2(temp);
00320         ss2 >> current_run;
00321         getline(ss1, temp, ' ');
00322         istringstream ss3(temp);
00323         ss3 >> current_event;
00324     }
00325 
00326 
00327     return 0;
00328 }
00329 
00330 
00331     
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on 20 Jun 2014 for daqman by  doxygen 1.6.1