SpeFinder.cc

00001 #include "EventHandler.hh"
00002 #include "SpeFinder.hh"
00003 #include "ConvertData.hh"
00004 #include "RootWriter.hh"
00005 //#include "S1S2Evaluation.hh"
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   //AddDependency<S1S2Evaluation>();
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   // only process real channels
00061   if(chdata->channel_id < 0 ) {
00062     Message(DEBUG2)<<"channel_id < 0"<<std::endl;
00063     return 0;
00064   }
00065   //need a good baseline
00066   if(!chdata->baseline.found_baseline) {
00067     Message(DEBUG2)<<"Baseline is no good"<<std::endl;
00068     return 0;
00069   }
00070   //make sure there is a good pulse found (do we need this?)
00071   if(!curr_ev_data->s1_valid)
00072     Message(DEBUG2)<<"No valid s1"<<std::endl;
00073   //return 0;
00074 
00075   //convert the window lengths in time to sample numbers
00076   const int winscan =
00077     chdata->TimeToSample(//curr_ev_data->s1_start_time +
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   //end the search at the end of the DAQ window
00086   int nsamps = chdata->nsamps-3;
00087   //chdata->TimeToSample(curr_ev_data->s1_end_time); to end of s1
00088   double* wave = chdata->GetBaselineSubtractedWaveform();
00089   double start_wave=wave[winscan];
00090   //previous is the sample index of the last located pulse
00091   int previous=0;
00092   /* search starting at search_start_time and go until the end of the trigger
00093      leave room for the integration and post_window ranges */
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       //we've found a peak, so update the previous designation
00114       int last_previous = previous;
00115       previous = samp;
00116 
00117       //case 1: this is the first peak, so we need to search the area before
00118       if(last_previous == 0 && (samp-winscan < winphe+winphe_bef) ){
00119         Message(DEBUG2)<<current_time<<": this is the first peak"<<std::endl;
00120         /*this is the first peak, and we haven't searched the area behind
00121           look back and make sure there are no peaks in the pre area*/
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           // there was a peak before this one that will mess stuff up, so skip
00142           continue;
00143         }
00144       }
00145 
00146       //case 2: we are too close to the previous peak (don't care anymore)
00147 
00148       // evaluate the local baseline within the winphe_bef window
00149       double local_baseline = std::accumulate( wave+(samp-winphe_bef),
00150                                                wave+samp, 0. ) / winphe_bef;
00151 
00152       /*Check for the end of the pulse. Find the point at which the wave goes
00153         back to close to the original value.*/
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       } //End check for pulse end
00198       if(end_sample == nsamps) { //We went to the end of the window
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       //is there another peak in the post area? We don't check any more
00207       test_sample=end_sample-1; //It will get incremented at the end of the loop
00208       //if we get here, this peak is good
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       //correct for edges
00215       /*integral-=wave[samp]/2.;
00216         integral+=wave[end_sample]/2.;*/
00217       //pulses are negative, but make the amplitude positive
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       //store everything in the tree
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       //have we found the max number yet?
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     }//end if statement looking for start of pulse
00257   } //end for loop over samples
00258   Message(DEBUG2)<<"SpeFinder ending"<<std::endl
00259                 <<n_peaks_found<<" peaks found"<<std::endl;
00260   return 0;
00261 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on 20 Jun 2014 for daqman by  doxygen 1.6.1