Diana Software
QTriggerBULLDAQ.cc
Go to the documentation of this file.
1 #include "QTriggerBULLDAQ.hh"
2 #include "QReader.hh"
3 #include "TMath.h"
4 #include <vector>
5 #include "QVector.hh"
6 #include <set>
7 
8 ClassImp(Diana::QTriggerBULLDAQ);
9 using std::endl;
10 using std::cout;
11 using std::cerr;
12 using Diana::QVector;
13 
15 
17  if(reader==0){
18  cout<<"NO READER PASSED TO TRIGGER"<<endl;
19  exit(-1);
20  }
21 
22  SetCFGParameters(reader->GetDouble(("ThresholdInRMS"+triggerLabel).c_str(),5.),reader->GetDouble(("LowPassFrequency"+triggerLabel).c_str(),50));
23 }
24 
25 
26 
27 void QTriggerBULLDAQ::TriggerStream(const vector<double>& stream){
28  //if parameters not read from cfg
29  if (!read_parameters){
31  }
32 
33 
34  //empty triggers
35  triggers.clear();
36  triggerHeights.clear();
37  filteredStream.clear();
38 
39  if(samplingFrequency ==0 or windowsize==0)cout<<"Sampling frequecy " << samplingFrequency <<"\tWindow Size = "<<windowsize<<endl;
40 
41 
42  int npoints = TMath::FloorNint(TMath::Sqrt(0.196202+(fCutoff/samplingFrequency)*(fCutoff/samplingFrequency))/(fCutoff/samplingFrequency)); //dsp.stackexchange.com/questions/9966/what-is-the-cut-off-frequency-of-a-moving-average-filter
43  if(npoints<1) npoints=1;
44  int triggerDelay = 2;//npoints-1;
45 
46 
47  QVector pulse (stream.size());
48 
49  //Differentiate (high pass filter)
50  for(size_t i = stream.size()-1; i > 0; i--){
51  pulse[i] =(double)( stream[i] - stream[i-1] );
52  }
53  pulse[0] = pulse[1];
54 
55 
56  //Integrate (pulse height reconstruction)
57  for(size_t i =0; i<pulse.Size();i++){
58  if(i<pulse.Size()-npoints){
59  pulse[i] = pulse.Sum(npoints,i);
60  }else {
61  pulse[i]=pulse[i-1];
62  }
63  }
64 
65 
66  //Moving Average (low pass filter) // made on reverse to remove time shift on filters
67  for(int i = (int)pulse.Size()-1; i>-1;i--){
68  if(i>=npoints){
69  pulse[i] = pulse.GetMean(npoints,i-npoints);
70  }else{
71  pulse[i]=pulse[i+1];
72  }
73  }
74 
75  //Find RMS
76  if(rms ==-1){
77  //int step = TMath::FloorNint((double)windowsize/10);//chosen because of dsp.stackexchange.com/questions/24468/derivative-filter-transfer-function
78  int step = TMath::FloorNint(samplingFrequency/10);//chosen because of dsp.stackexchange.com/questions/24468/derivative-filter-transfer-function
79  if((size_t)(4*step)>pulse.Size()){
80  step = TMath::FloorNint((double)windowsize/5);//chosen because of dsp.stackexchange.com/questions/24468/derivative-filter-transfer-function
81 
82  }
83  double rms_new=-1;
84  std::set<double> rmsss;
85  for(size_t i =0; i<pulse.Size()-step;i+=step){
86  if(rms_new ==-1){
87  rms_new = pulse.GetSubVector(step,i).GetRMS();
88  rms = rms_new +1;
89  }else{
90  rms_new = pulse.GetSubVector(step,i).GetRMS();
91  }
92  if(rms_new<=rms and rms_new>0){
93  rms=rms_new;
94  }
95  if (rms_new>0)rmsss.insert(rms_new);
96  }
97  std::set<double>::const_iterator it=rmsss.cbegin();
98  std::advance(it,rmsss.size()/2);
99  double median=*it;
100  if (rmsss.size()%2==0){
101  median = (median + *std::prev(it))/2;
102  }
103  }
104  for (size_t i =0 ; i < pulse.Size();i++){
105  filteredStream.push_back(pulse[i]);
106  }
107 
108  size_t first_trig=pulse.Size()+1;
109  size_t prev_trig=first_trig;
110  double height =0;
111  size_t sample;
112  for(size_t i=0; i<pulse.Size();i++){
113  if(pulse[i]>=triggerLevel*rms){//If sample triggers
114  if(first_trig==pulse.Size()+1){//first trigger point in chunk
115  first_trig = i;
116  prev_trig = i;
117  }else if (i==prev_trig+1){//same peak
118  prev_trig=i;
119  }else if(i>prev_trig+1){//new peak
120  first_trig=i;
121  prev_trig=i;
122  }
123  }
124  if((i==prev_trig+1 and pulse[i]<triggerLevel*rms) or (i == pulse.Size()-1 and i ==prev_trig)){//as soon as the peak ends or if the peak is ongoing and we are at the end of the stream
125 
126  if(triggers.size()==0){
127  for(size_t j = first_trig; j<=prev_trig;j++){
128  if(j==first_trig){
129  height=pulse[j];
130  sample=j;
131  }else{
132  if(height<pulse[j]){
133  height=pulse[j];
134  sample=j;
135  }
136  }
137  }
138 
139  triggers.push_back((int)sample-triggerDelay);
140  triggerHeights.push_back(height);
141  }else{
142  if((double)((int)first_trig-triggers[triggers.size()-1]) >= (double)debounce){//don't trigger if trigger is too near the previous one
143  for(size_t j =first_trig; j<=prev_trig;j++){
144  if(j==first_trig){
145  height=pulse[j];
146  sample=j;
147  }else{
148  if(height<pulse[j]){
149  height=pulse[j];
150  sample=j;
151  }
152  }
153  }
154  triggers.push_back((int)sample-triggerDelay);
155  triggerHeights.push_back(height);
156  }
157  }
158  }
159  }
160 }
161 
162 
163 
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
ClassImp(Diana::QTriggerBULLDAQ)
double GetDouble(const std::string &parname, double defVal, bool warnCfg=true) const
Get a double parameter from config file.
Definition: QBaseModule.cc:184
void GetParametersFromCFG()
void TriggerStream(const vector< double > &stream)
void SetCFGParameters(double trigLevl=5., double cutoff=50.)
int windowsize
Definition: QTrigger.hh:104
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 vectors in Diana analysis.
Definition: QVector.hh:30
UInt_t Size() const
size of QVector
Definition: QVector.hh:54
double GetMean(const UInt_t nelem, const UInt_t first=0) const
Get Mean.
Definition: QVector.hh:326
QVector GetSubVector(UInt_t size, UInt_t start=0, UInt_t stride=1)
Definition: QVector.cc:701
double GetRMS(const UInt_t nelem, const UInt_t first=0) const
Get RMS.
Definition: QVector.cc:632
double Sum(UInt_t nelem, UInt_t first=0) const
sum elements
Definition: QVector.cc:624