SpeFinder.cc
00001 #include "EventHandler.hh"
00002 #include "SpeFinder.hh"
00003 #include "ConvertData.hh"
00004 #include "RootWriter.hh"
00005
00006 #include "BaselineFinder.hh"
00007 #include <vector>
00008 #include <numeric>
00009
00010 SpeFinder::SpeFinder():
00011 ChannelModule(GetDefaultName(), "Search for single photoelectrons in the tails of pulses identified by PulseFinder")
00012 {
00013
00014 AddDependency<BaselineFinder>();
00015 RegisterParameter("search_start_time", search_start_time = 5.,
00016 "Time from start of pulse to begin search [us]");
00017 RegisterParameter("rough_threshold", rough_threshold = 7,
00018 "Value by which waveform must drop over 2 samples");
00019 RegisterParameter("threshold_fraction",threshold_fraction = 0,
00020 "Fraction of threshold that nearby sample has to overcome");
00021 RegisterParameter("return_fraction",return_fraction = 0.1,
00022 "Fraction of threshold that indicates return to baseline");
00023 RegisterParameter("fine_threshold", fine_threshold = 7,
00024 "Threshold value looking for secondary peaks");
00025 RegisterParameter("pre_window", pre_window = 0.04,
00026 "Time in us to evaluate local baseline before pulse");
00027 RegisterParameter("post_window",post_window = 0.04,
00028 "Time in us after pulse to ensure return to 0");
00029 RegisterParameter("pulse_window", pulse_window = 0.032,
00030 "Window where we expect the bulk of the pulse to arrive");
00031 RegisterParameter("max_photons", max_photons=10,
00032 "Maximum number of photons to find per event before exit");
00033 RegisterParameter("debug",debug=false,
00034 "If true, more steps will be printed to standard output");
00035 }
00036
00037 SpeFinder::~SpeFinder()
00038 {
00039 Finalize();
00040 }
00041
00042 int SpeFinder::Initialize()
00043 {
00044 return 0;
00045 }
00046
00047 int SpeFinder::Finalize()
00048 {
00049 return 0;
00050 }
00051
00052 int SpeFinder::Process(ChannelData* chdata)
00053 {
00054 double debug_start = -0.02;
00055 double debug_end = 0.06;
00056 int n_peaks_found=0;
00057 EventDataPtr curr_ev_data = _current_event->GetEventData();
00058 Message(DEBUG2)<<"SpeFinder starting on event "<<curr_ev_data->event_id
00059 <<std::endl;
00060
00061 if(chdata->channel_id < 0 ) {
00062 Message(DEBUG2)<<"channel_id < 0"<<std::endl;
00063 return 0;
00064 }
00065
00066 if(!chdata->baseline.found_baseline) {
00067 Message(DEBUG2)<<"Baseline is no good"<<std::endl;
00068 return 0;
00069 }
00070
00071 if(!curr_ev_data->s1_valid)
00072 Message(DEBUG2)<<"No valid s1"<<std::endl;
00073
00074
00075
00076 const int winscan =
00077 chdata->TimeToSample(
00078 search_start_time);
00079 Message(DEBUG2)<<"Start search@"<<chdata->SampleToTime(winscan)
00080 <<", which is sample "<<winscan<<std::endl;
00081 int winphe_bef = (int)(pre_window * chdata->sample_rate);
00082 int winphe_after = (int)(post_window * chdata->sample_rate);
00083 const int winphe = (int)(pulse_window * chdata->sample_rate);
00084
00085
00086 int nsamps = chdata->nsamps-3;
00087
00088 double* wave = chdata->GetBaselineSubtractedWaveform();
00089 double start_wave=wave[winscan];
00090
00091 int previous=0;
00092
00093
00094 bool secondary_pulse = false;
00095 bool prev_sec_pulse = false;
00096 double prev_loc_bl = 0;
00097 for(int test_sample = winscan; test_sample < nsamps; test_sample++){
00098 prev_sec_pulse = secondary_pulse;
00099 double current_time=chdata->SampleToTime(test_sample);
00100 if(current_time>=debug_start && current_time<=debug_end)
00101 Message(DEBUG2)<<"At "<<current_time<<"us the amplitude is "
00102 <<wave[test_sample]<<std::endl;
00103 if(( wave[test_sample] - wave[test_sample+2] >= rough_threshold &&
00104 ( ( (wave[test_sample+1]-wave[test_sample])/
00105 (wave[test_sample+2]-wave[test_sample]) >= 0) ||
00106 ( (wave[test_sample+3]-wave[test_sample])/
00107 (wave[test_sample+2]-wave[test_sample]) >= 0) ) ) ||
00108 secondary_pulse) {
00109
00110 const int samp = test_sample;
00111 if(!secondary_pulse)
00112 start_wave=wave[samp];
00113
00114 int last_previous = previous;
00115 previous = samp;
00116
00117
00118 if(last_previous == 0 && (samp-winscan < winphe+winphe_bef) ){
00119 Message(DEBUG2)<<current_time<<": this is the first peak"<<std::endl;
00120
00121
00122 bool pre_peak_found = false;
00123 for(int presample = samp - (winphe+winphe_bef);
00124 presample < samp; presample++){
00125 if( (wave[presample] - wave[presample+2] >= fine_threshold) &&
00126 (wave[presample+1] <= wave[presample] ) &&
00127 (wave[presample+2] <= wave[presample+1] ) ){
00128 pre_peak_found = true;
00129 Message(DEBUG2)<<"samp = "<<chdata->SampleToTime(samp)<<std::endl
00130 <<"presample = "<<chdata->SampleToTime(presample)
00131 <<std::endl
00132 <<"wave[ps] = "<<wave[presample]<<std::endl
00133 <<"wave[ps+1] = "<<wave[presample+1]<<std::endl
00134 <<"wave[ps+2] = "<<wave[presample+2]<<std::endl
00135 <<"."<<std::endl;
00136 break;
00137 }
00138 }
00139 if(pre_peak_found){
00140 Message(DEBUG2)<<current_time<<": pre_peak_found"<<std::endl;
00141
00142 continue;
00143 }
00144 }
00145
00146
00147
00148
00149 double local_baseline = std::accumulate( wave+(samp-winphe_bef),
00150 wave+samp, 0. ) / winphe_bef;
00151
00152
00153
00154 int end_sample = samp+3;
00155 if(current_time>debug_start && current_time<debug_end) {
00156 Message(DEBUG2)<<chdata->SampleToTime(samp)<<"\t"
00157 <<wave[samp]<<std::endl
00158 <<chdata->SampleToTime(samp+1)<<"\t"
00159 <<wave[samp+1]<<std::endl
00160 <<chdata->SampleToTime(samp+2)<<"\t"
00161 <<wave[samp+2]<<std::endl;
00162 }
00163 for(int exit_sample = samp+3; exit_sample <= nsamps; ++exit_sample) {
00164 if(current_time>debug_start && current_time<debug_end)
00165 Message(DEBUG2)<<"\tThen "<<wave[exit_sample]<<" ("
00166 <<wave[exit_sample-1]<<") at "
00167 <<chdata->SampleToTime(exit_sample)<<std::endl;
00168 if(-wave[exit_sample]<=return_fraction*rough_threshold) {
00169 ++end_sample;
00170 secondary_pulse = false;
00171 Message(DEBUG2)<<"\nEnded because of return fraction"<<std::endl;
00172 break;
00173 }
00174 if((wave[exit_sample]>=wave[exit_sample-1] &&
00175 (wave[exit_sample-1]>=wave[exit_sample-2] ||
00176 fabs(wave[exit_sample-1]-wave[exit_sample-2])<=
00177 0.01*std::min(fabs(wave[exit_sample-1]),
00178 fabs(wave[exit_sample-2]))) &&
00179 wave[exit_sample]>=wave[exit_sample+1]+fine_threshold)
00180 ||
00181 (wave[exit_sample]>=wave[exit_sample-1]+fine_threshold &&
00182 wave[exit_sample]>=wave[exit_sample+1]+fine_threshold)
00183 ||
00184 (wave[exit_sample]>=wave[exit_sample-1]+fine_threshold &&
00185 wave[exit_sample]>=wave[exit_sample+2]+fine_threshold &&
00186 (wave[exit_sample]>=wave[exit_sample+1] ||
00187 fabs(wave[exit_sample]-wave[exit_sample+1])<=
00188 0.01*std::min(fabs(wave[exit_sample]),
00189 fabs(wave[exit_sample+1]))))
00190 ) {
00191 Message(DEBUG2)<<"\nEnded because another pulse was found"<<std::endl;
00192 end_sample=exit_sample;
00193 secondary_pulse = true;
00194 break;
00195 }
00196 end_sample=exit_sample;
00197 }
00198 if(end_sample == nsamps) {
00199 Message(DEBUG2)<<current_time<<": We went to the end of the window"
00200 <<std::endl;
00201 secondary_pulse = false;
00202 continue;
00203 }
00204 Message(DEBUG2)<<"end_sample: "<<chdata->SampleToTime(end_sample)
00205 <<std::endl;
00206
00207 test_sample=end_sample-1;
00208
00209 Message(DEBUG2)<<chdata->SampleToTime(samp)<<","
00210 <<chdata->SampleToTime(end_sample)<<std::endl;
00211 double integral =
00212 (secondary_pulse ? std::accumulate(wave+samp,wave+end_sample,0.) :
00213 std::accumulate(wave+samp,wave+end_sample+winphe_after,0.));
00214
00215
00216
00217
00218 integral =- integral;
00219 Message(DEBUG2)<<"integral: "<<integral<<std::endl;
00220 int max_sample =
00221 (secondary_pulse ? std::min_element(wave+samp,wave+end_sample)-wave :
00222 std::min_element(wave+samp,wave+end_sample+winphe_after) - wave);
00223
00224
00225 Spe found_spe;
00226 found_spe.integral = integral;
00227 found_spe.start_time = chdata->SampleToTime(samp);
00228 found_spe.amplitude = - wave[max_sample];
00229 found_spe.peak_time = chdata->SampleToTime(max_sample);
00230 if(prev_sec_pulse)
00231 found_spe.local_baseline =
00232 (secondary_pulse ? prev_loc_bl :
00233 std::accumulate(wave+end_sample,wave+end_sample+winphe_after,0.)/
00234 winphe_after);
00235 else
00236 found_spe.local_baseline = local_baseline;
00237 found_spe.length = (end_sample-samp)*1.0/chdata->sample_rate;
00238 if(!secondary_pulse && fabs(wave[end_sample])<=rough_threshold)
00239 found_spe.length += post_window;
00240
00241 chdata->single_pe.push_back(found_spe);
00242 ++n_peaks_found;
00243 Message(DEBUG2)<<"Found good one: "<<current_time<<", end point: "
00244 <<chdata->SampleToTime(end_sample)<<std::endl
00245 <<"There are "<<chdata->single_pe.size()<<" spes"
00246 <<std::endl;
00247
00248 if(chdata->single_pe.size() >= (size_t)max_photons) {
00249 Message(DEBUG2)<<current_time
00250 <<"\nWe have found the max number of photons already"
00251 <<std::endl;
00252 return 0;
00253 }
00254 if(!prev_sec_pulse)
00255 prev_loc_bl = local_baseline;
00256 }
00257 }
00258 Message(DEBUG2)<<"SpeFinder ending"<<std::endl
00259 <<n_peaks_found<<" peaks found"<<std::endl;
00260 return 0;
00261 }