Diana Software
QTriggerOptimumFilter.cc
Go to the documentation of this file.
2 #include "TMath.h"
3 #include <vector>
4 #include <numeric>
5 #include "QGlobalDataManager.hh"
6 #include "QAveragePulseHandle.hh"
7 #include "QAverageNoiseHandle.hh"
8 
9 
10 ClassImp(Diana::QTriggerOptimumFilter);
11 using std::endl;
12 using std::cout;
13 using std::cerr;
14 using Diana::QVector;
15 using Diana::QVectorC;
16 
18 
20  if(reader==0){
21  cout<<"NO READER PASSED TO TRIGGER"<<endl;
22  exit(-1);
23  }
24  SetCFGParameters(reader->GetString(("AveragePulse"+triggerLabel),""),reader->GetString(("AverageNoisePS"+triggerLabel),""),reader->GetInt(("Dataset"+triggerLabel),1,true), reader->GetDouble(("ThresholdInRMS"+triggerLabel).c_str(),5.),reader->GetDouble(("ReceedLevel"+triggerLabel).c_str(),2.),reader->GetString(("AvgPulseOwner"+triggerLabel),"AveragePulses",false),reader->GetString(("AvgNoiseOwner"+triggerLabel),"NoiseAvgPowerSpectrum",false));
25 }
26 
27 const QVector& QTriggerOptimumFilter::Filter(const QVector& window_stream){
28  QVectorC stream_FD;
29  filt_stream_window.Clear();
30  if((int)window_stream.Size()!=2*windowsize){
31  cout<<"FATAL ERROR: Stream not the right size"<<endl;
32  cout<<"Size should be "<<2*windowsize<<" Found instead "<<window_stream.Size()<<endl;
33  }
34  fTransformer_d->TransformToFreq(window_stream,stream_FD);
35  stream_FD[0].Set(0,0);
36  fTransformer_d->TransformFromFreq(fFilterFD_d.Mult(stream_FD),filt_stream_window);
37  return filt_stream_window;
38 }
39 
41 
42  Diana::QGlobalDataManager dm;
43 
44  // Get Average pulse
45  /*string apowner = "AveragePulses";
46  string anowner = "NoiseAvgPowerSpectrum";
47  if(extraLabel.compare("")!=0){
48  apowner += "_";
49  apowner += extraLabel;
50  anowner += "_";
51  anowner += extraLabel;
52  }*/
53 
55  aph.SetDataset(dataset);
57  if (!aph.IsValid()){
58  cout<<"Impossible to read average pulse"<<endl;
59  cout<<err.ToString()<<"\t"<<err.GetDescription()<<endl;
60  return false;
61  }
62 
63  ap = aph.Get();
64  ap = ap - ap[0];
65  ap_max_norm = ap.GetMax();
66  ap/=ap.GetMax();
67  //int apmaxIndex = ap.GetMaxIndex();
68 
70  anh.SetDataset(dataset);
71  err = dm.Get(anowner,&anh,average_noise);
72  if (!anh.IsValid()){
73  cout<<"Impossible to read average noise"<<endl;
74  cout<<err.ToString()<<"\t"<<err.GetDescription()<<endl;
75  return false;
76  }
77  an = anh.Get();
78  an[0]=0;
79 
80  fTransformer = new QRealComplexFFT(ap.Size());
81  fTransformer_d= new QRealComplexFFT(2*ap.Size());
82 
83  smoothing_ap.Resize(ap.Size());
84  size_t i = 1;
85  size_t transient =0;
86  while(transient <= 0){
87  transient = (2*i*ap.Size())/25;
88  i++;
89  }
90  for(size_t i= 0; i<smoothing_ap.Size();i++){
91  if(2*i<=transient){
92  smoothing_ap[i] = TMath::Cos(2*TMath::Pi()*i/transient+TMath::Pi()) * 0.5 +0.5;
93  }else if(2*i>=(2*smoothing_ap.Size() - transient)){
94  smoothing_ap[i] = TMath::Cos(2*TMath::Pi()*i/transient) * 0.5 +0.5;
95  }else{
96  smoothing_ap[i] = 1;
97  }
98  }
99 
100  smoothed_ap = ap.Mult(smoothing_ap);
101 
102 
103  fTransformer->TransformToFreq(smoothed_ap,ap_FD);
104 
105  QVector SNR = ap_FD.GetModulusSquare().Div(an);
106  double M = 1./SNR.Sum(ap.Size()-1,1);
107 
108  fFilter1 = M*ap_FD.Conj().Div(an);
109  fFilter1 *= ap.Size();
110  fFilter1[0].Set(0,0);
111 
112 
113  fTransformer->TransformFromFreq(fFilter1,fFilterTD);
114 
115  fFilterTD_d.Resize(2*fFilterTD.Size());
116  fFilterTD_d.Initialize(0);
117  QVector filtertmp = fFilterTD.Mult(smoothing_ap);
118  for(size_t i = 0; i<fFilterTD.Size();i++){
119  filtertmp.Append(0);
120  }
121  fFilterTD_d = filtertmp.Shift((3*fFilterTD.Size())/2);
122  fTransformer_d->TransformToFreq(fFilterTD_d,fFilterFD_d);
123 
124  rms = TMath::Sqrt(M);
125  windowsize = (int)ap.Size();
127 
128 
129  ap_d.Resize(2*ap.Size());
130  ap_d.Initialize(0);
131  for(size_t i = 0; i<ap.Size();i++){
132  ap_d[i+ap.Size()/2]=ap[i];
133  }
134 
135 
136  apfilt = Filter(ap_d);
137  int max_index = ap_d.GetMaxIndex();
138  double threshold = ap_d[max_index]/receed_lvl;
139  int threshold_index = max_index/2;
140  i = (size_t)max_index;
141  while( (ap_d[i]-threshold)>=0 and (i>=0)){
142  threshold_index=i;
143  i--;
144  }
145  if((threshold - ap_d[threshold_index])>(ap_d[threshold_index+1]-threshold)){
146  threshold_index+=1;
147  }
148  threshold_index = max_index - threshold_index;
149  IndexDifference = (ap.Size() -max_index +threshold_index);
151  return true;
152 }
153 
154 void QTriggerOptimumFilter::TriggerStream(const vector<double>& stream){
155  if (!optimum_filter_built){
156  //reader->Debug("Building OF");
157  cout<<"Building OF"<<endl;
158  if(!read_parameters){
160  }
162  }
163  //empty triggers
164  triggers.clear();
165  triggerHeights.clear();
166  filteredStream.clear();
167 
168  if(samplingFrequency ==0 or windowsize==0)cout<<"Sampling frequecy "<<samplingFrequency<<"Hz"<< "\t Window Size = "<<windowsize<<endl;
169 
170 
171 
172  QVector filtered_win;
173  QVector win(2 * windowsize);
174  win.Initialize(0);
175  for(size_t i = 0; i<(size_t)windowsize and i<stream.size() ;i++){
176  win[i] = stream[i]-stream[0];
177  }
178 
179  win=win.Shift(windowsize/2);
180  //if((int)stream.size()<2*windowsize){
181  //}
182  //for(size_t i = 0; i<(size_t)win.Size();i++){
183  // cout<<win[i]<<",";
184  //}
185  //cout<<endl<<endl;
186  filtered_win = Filter(win);
187  //for(size_t i = 0 ; i<filtered_win.Size();i++){
188  // cout<<filtered_win[i]<<",";
189  //}
190  //cout<<endl<<endl;
191 // for(size_t i = 0 ; i<(size_t)((double)windowsize*1.5);i++){
192  for(size_t i = 0; i<(size_t)windowsize;i++){
193  filteredStream.push_back(filtered_win[(windowsize/2)+i]);
194  }
195 
196  for(size_t i =(size_t)(windowsize*0.5);i<stream.size();i+=(size_t)(windowsize)){
197  if(i+2*windowsize<stream.size()){
198  win = vector<double> (stream.begin()+i, stream.begin()+i+2*windowsize);
199  win = win - stream[i];
200  }else{
201  win.Resize(2*windowsize);
202  win.Initialize(0);
203  for(size_t k = 0; k<stream.size()-i;k++){
204  win[k]=stream[i+k]-stream[i];
205  }
206  win=win.Shift(windowsize/2);
207  }
208 
209  filtered_win = Filter(win);
210 
211  for(size_t j = 0;j<(size_t)windowsize;j++){
212  filteredStream.push_back(filtered_win[j+(size_t)((double)windowsize*0.5)]);
213  }
214  }
215 
216 
217  filteredStream.resize(stream.size());
218 
219  vector<int> sample_idx(filteredStream.size());
220  vector<bool> enabled(filteredStream.size(),true);
221  vector<int> mapping(filteredStream.size(),true);
222 
223  std::iota(sample_idx.begin(),sample_idx.end(),0); //Initializing
224  sort( sample_idx.begin(),sample_idx.end(), [&](int i,int j){return filteredStream[i]>filteredStream[j];} );
225 
226  std::iota(mapping.begin(),mapping.end(),0); //Initializing
227  sort(mapping.begin(),mapping.end(), [&](int i,int j){return sample_idx[i]<sample_idx[j];});
228 
229  for(size_t i = 0; i<enabled.size();i++){
230  while(i <enabled.size()){
231  if(enabled[i]==true) break;
232  i++;
233  }
234 
235  if(i==enabled.size()) break;
236  if(filteredStream[sample_idx[i]] <= rms*triggerLevel) break;
237  enabled[i] = false;
238 
239  if((sample_idx[i]-IndexDifference)>=0){
240  triggers.push_back(sample_idx[i]-IndexDifference);
241  triggerHeights.push_back(filteredStream[sample_idx[i]]);
242  }else{
243  triggers.push_back(sample_idx[i]);
244  triggerHeights.push_back(filteredStream[sample_idx[i]]);
245  }
246  int min_deb = debounce*4/5;
247  int max_deb = debounce/5;
248  while(sample_idx[i]-min_deb<0){
249  min_deb--;
250  }
251  while(sample_idx[i]+max_deb>=(int)enabled.size()){
252  max_deb--;
253  }
254  for(int j = -min_deb; j<max_deb;j++){
255  enabled[mapping[sample_idx[i]+j]] = false;
256  }
257 
258  }
259 }
260 
261 
262 
err
Definition: CheckOF.C:114
QGlobalDataManager dm
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
ClassImp(Diana::QTriggerOptimumFilter)
global handle for average noise power spectra
global handle for average pulse
const std::string & GetString(const std::string &parname, const std::string &defVal, bool warnCfg=true) const
Get a string parameter from config file ( see GetDouble() )
Definition: QBaseModule.cc:297
double GetDouble(const std::string &parname, double defVal, bool warnCfg=true) const
Get a double parameter from config file.
Definition: QBaseModule.cc:184
int GetInt(const std::string &parname, int defVal, bool warnCfg=true) const
Get an int parameter from config file ( see GetDouble() )
Definition: QBaseModule.cc:219
error class with error type and description
Definition: QError.hh:115
QError Get(const std::string &owner, GlobalHandle< Q > *gh, const std::string &inSource, bool printError=true) const
Get an object using a global handle.
Wrapper for a specific QRealComplexFFT algorithm class.
Diana::QRealComplexFFT * fTransformer
void SetCFGParameters(string apinput="", string aninput="", int ds=1, double trigLevl=5., double receed=2., string APOwner="AveragePulses", string ANOwner="NoiseAvgPowerSpectrum")
void TriggerStream(const vector< double > &stream)
Diana::QRealComplexFFT * fTransformer_d
const Diana::QVector & Filter(const QVector &window_stream)
int windowsize
Definition: QTrigger.hh:104
int chan
Definition: QTrigger.hh:116
vector< int > triggers
Definition: QTrigger.hh:98
double samplingFrequency
Definition: QTrigger.hh:102
string triggerLabel
Definition: QTrigger.hh:112
vector< double > triggerHeights
Definition: QTrigger.hh:99
vector< double > filteredStream
Definition: QTrigger.hh:100
double rms
Definition: QTrigger.hh:108
int debounce
Definition: QTrigger.hh:106
const QBaseModule * reader
Definition: QTrigger.hh:110
Interface for complex vectors in Diana analysis.
Definition: QVectorC.hh:25
Interface for vectors in Diana analysis.
Definition: QVector.hh:30
UInt_t Size() const
size of QVector
Definition: QVector.hh:54
const QVector & Shift(const int nstep)
Cyclic shift of vector.
Definition: QVector.cc:395
void Append(const double val)
append
Definition: QVector.cc:597
double Sum(UInt_t nelem, UInt_t first=0) const
sum elements
Definition: QVector.cc:624
void Resize(const UInt_t newsize)
resize a QVector
Definition: QVector.cc:170
void Initialize(const double val=0)
initialize elements (default to 0)
Definition: QVector.cc:218