Diana Software
QFir.cc
Go to the documentation of this file.
1 #include "QFir.hh"
2 #include <sstream>
3 #include <cmath>
4 #include <gsl/gsl_sf_bessel.h>
5 #include <iostream>
6 
8 
9 
10 using namespace Diana;
11 using namespace std;
12 
13 QFir::QFir(const QCFirData& configuration) :
14 fConfiguration(configuration),
15 fCoefficients(configuration.fM)
16 {
17 
18  if(fConfiguration.fM%2 == 0) {
20  std::stringstream msg;
21  msg<<"Size of filter must be odd. You supplied ("<<fConfiguration.fM<<")";
22  err.SetDescription(__FILE__,__LINE__,msg.str());
23  throw err;
24  }
25  fFilterReduction = 0;
27  QVector theta(fConfiguration.fM*2), outputTheta;
28  theta.Initialize(0);
29  for(int i = fConfiguration.fM; i < 2*fConfiguration.fM; i++) {
30  theta[i] = 1;
31  }
32  Filter(theta,outputTheta);
33  double t10=-1,t50=-1,t90=-1;
34  for(size_t i = 0; i < outputTheta.Size(); i++) {
35  if(outputTheta[i]>0.9 && t90<0) {
36  if(i>0) t90=i+(0.9-outputTheta[i])/(outputTheta[i]-outputTheta[i-1]);
37  else t90 = i;
38  }
39  if(outputTheta[i]>0.5 && t50<0) {
40  if(i>0) t50=i+(0.5-outputTheta[i])/(outputTheta[i]-outputTheta[i-1]);
41  else t50 = i;
42  }
43  if(outputTheta[i]>0.1 && t10<0) {
44  if(i>0) t10=i+(0.1-outputTheta[i])/(outputTheta[i]-outputTheta[i-1]);
45  else t10 = i;
46  }
47  }
48  fDelay = t50-fConfiguration.fM;
49  fRiseTime = t90-t10;
50 }
51 
53 {
55  fCoefficients.clear();
56  fFilteredSize = 0;
57  fFilterReduction = 0;
60 }
61 
62 
63 QError QFir::Filter(const QVector& input, QVector& output) const
64 {
65  size_t M = fCoefficients.size();
66  if(input.Size() <= fFilterReduction) {
68  std::stringstream msg;
69  msg<<"Input vector size ("<<input.Size()<<")"
70  <<" is <= the filter reduction ("<<fFilterReduction<<")";
71  err.SetDescription(__FILE__,__LINE__,msg.str());
72  return err;
73  }
74  size_t N = input.Size()-fFilterReduction;
75  output.Resize(N);
76  for(size_t i = 0; i < N; i++) {
77  output[i] = 0;
78  for(size_t j = 0; j < M; j++) {
79  output[i] += fCoefficients[j]*input[i+j];
80  }
81  }
82 
83  return QERR_SUCCESS;
84 }
85 
87 {
88  // from http://www.arc.id.au/FilterDesign.html
89  int M = fCoefficients.size();
90  int Np = (M-1)/2;
91 
92  // filter
93  double period = (2.*M_PI);
94  fCoefficients[Np] = period*fConfiguration.fCutoff/M_PI ;
95  for(int j=1; j<Np; j++)
96  fCoefficients[j+Np] = sin(period*fConfiguration.fCutoff*(j))/(M_PI*(j));
97 
98  // window
99  double Alpha;
100  if (fConfiguration.fAttDB<21)
101  Alpha = 0;
102  else if (fConfiguration.fAttDB>50)
103  Alpha = 0.1102*(fConfiguration.fAttDB-8.7);
104  else
105  Alpha = 0.5842*pow((fConfiguration.fAttDB-21), 0.4)+0.07886*(fConfiguration.fAttDB-21);
106  double IAlpha = gsl_sf_bessel_I0 (Alpha);
107 
108  for(int j=0; j<=Np; j++){
109  double arg = Alpha*sqrt(1.-pow(double(j)/Np,2));
110  double window = gsl_sf_bessel_I0(arg)/IAlpha;
111  // cout<<"j: "<<j<<" w:"<<window<<" s:"<<fCoefficients[j+Np]<<endl;
112  fCoefficients[j+Np] *= window;
113  }
114 
115  // symmetrize
116  for(int j = 0; j < Np; j++){
117  fCoefficients[j] = fCoefficients[M-j-1];
118  }
119 
120  // correct gain if != 1
121  double area = 0;
122  for(size_t j = 0; j < fCoefficients.size(); j++) {
123  area += fCoefficients[j];
124  }
125  for(size_t j = 0; j < fCoefficients.size(); j++) {
126  fCoefficients[j]/=area;
127  }
128 
129 
130  fFilterReduction = M-1;
131  /*
132  for(int j = 0; j < M; j++) {
133  std::cout<<fCoefficients[j]<<" ";
134  }
135  */
136  // std::cout<<std::endl;
137 }
err
Definition: CheckOF.C:114
int N
Definition: CheckOF.C:24
Diana::QComplex pow(const Diana::QComplex &z, double a)
Raise a complex number to a real power.
Definition: QComplex.cc:246
#define Q_DOUBLE_DEFAULT
Definition: QDiana.hh:24
@ QERR_SIZE_NOT_MATCH
Definition: QError.hh:31
@ QERR_SUCCESS
Definition: QError.hh:27
QObjectImp(QFir)
Diana::QVector sin(const Diana::QVector &v)
Definition: QVector.cc:815
Data class for QFir (Ported from Calder)
Definition: QCFirData.hh:14
Method fMethod
Definition: QCFirData.hh:34
double fCutoff
Definition: QCFirData.hh:36
@ KayserBessel
Definition: QCFirData.hh:18
double fAttDB
Definition: QCFirData.hh:37
void Clear()
Definition: QCFirData.hh:22
error class with error type and description
Definition: QError.hh:115
QFir FIR low pass filter (Ported from Calder)
Definition: QFir.hh:17
size_t fFilteredSize
Definition: QFir.hh:37
void KayserBesselAlgorithm()
Definition: QFir.cc:86
QFir()
Definition: QFir.hh:19
QError Filter(const Diana::QVector &input, Diana::QVector &output) const
Definition: QFir.cc:63
size_t fFilterReduction
Definition: QFir.hh:38
QCFirData fConfiguration
Definition: QFir.hh:35
void Clear()
Definition: QFir.cc:52
std::vector< double > fCoefficients
Definition: QFir.hh:36
double fRiseTime
Definition: QFir.hh:39
double fDelay
Definition: QFir.hh:40
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...