Diana Software
BesselTransformer.cc
Go to the documentation of this file.
1 #include "BesselTransformer.hh"
2 #include "QRealComplexFFT.hh"
3 #include "QVectorView.hh"
4 #include <math.h>
5 
6 
7 BesselTransformer::BesselTransformer(double cutFreq, double duration, double samplFreq, double tauRC, bool zeroPad)
8 {
9  fDuration = duration;
10  fSize = (size_t) roundl(duration*samplFreq);
11  fZeroPad = zeroPad;
12 
13  fSamplingFrequency = samplFreq;
14  fCutFreq = cutFreq * duration;
15  if(tauRC > 0.) {
16  fRCFreq = 1./(tauRC*2*M_PI) * duration;
17  } else fRCFreq = -1.;
18 
19  double norm = 2.703395061;
20  fNormCutFreq = fCutFreq / norm;
21 
22  QVector besselSestoRe(fSize), besselSestoIm(fSize);
23  QVector rcRe(fSize), rcIm(fSize);
24  QVector transFunctionRe(fSize), transFunctionIm(fSize);
25 
26  for(size_t x = 0; x< fSize/2 + 1; x++) {
27  double xx = double(x) / fNormCutFreq;
28  double valBesselRe = 10395. - 4725.*pow(xx,2) + 210.*pow(xx,4) - pow(xx,6);
29  double valBesselIm =xx*( 10395.-1260.*pow(xx,2)+21.*pow(xx,4));
30  besselSestoRe(x) = 10395. * valBesselRe/(pow(valBesselRe,2)+pow(valBesselIm,2));
31  besselSestoIm(x) = -10395. * valBesselIm/(pow(valBesselRe,2)+pow(valBesselIm,2));
32  if(fRCFreq > 0. ) {
33  double xxrc = double(x)/fRCFreq;
34  rcRe(x) = 1./(1.+pow(xxrc,2));
35  rcIm(x) = -xxrc/(1.+pow(xxrc,2));
36  }
37  }
38 
39  for(size_t y = 0; y<(fSize/2-1); y++) {
40  double xx = - (fSize/2-1 - y);
41  xx/=fNormCutFreq;
42  double valBesselRe= 10395. - 4725.*pow(xx,2) + 210.*pow(xx,4) - pow(xx,6);
43  double valBesselIm=xx*( 10395.-1260.*pow(xx,2)+21.*pow(xx,4));
44  besselSestoRe(y+fSize/2+1) = 10395.*valBesselRe/(pow(valBesselRe,2)+pow(valBesselIm,2));
45  besselSestoIm(y+fSize/2+1) = -10395.*valBesselIm/(pow(valBesselRe,2)+pow(valBesselIm,2));
46  if(fRCFreq > 0.) {
47  double xxrc = double(- (fSize/2-1 - y))/fRCFreq;
48  rcRe(y+fSize/2+1) = 1./(1.+pow(xxrc,2));
49  rcIm(y+fSize/2+1) = -xxrc/(1.+pow(xxrc,2));
50  }
51  }
52 
53  for(size_t x = 0; x < fSize; x++) {
54  if(fRCFreq > 0.) {
55  transFunctionRe[x] = besselSestoRe[x]*rcRe[x] - besselSestoIm[x]*rcIm[x];
56  transFunctionIm[x] = besselSestoRe[x]*rcIm[x] + besselSestoIm[x]*rcRe[x];
57  } else {
58  transFunctionIm[x] = besselSestoIm[x];
59  transFunctionRe[x] = besselSestoRe[x];
60  }
61  // transFunctionIm[x] = rcIm[x];
62  // transFunctionRe[x] = rcRe[x];
63  }
64 
65  fTransferFunction.SetArray(transFunctionRe.GetConstArray(),transFunctionIm.GetConstArray(),fSize);
66  QRealComplexFFT transformer(fSize);
68 
69  // pad the second half with zeros to have good fft convolution
70  if(fZeroPad) {
71  size_t newsize = 2;
72  while(newsize < fSize) {
73  newsize *=2;
74  }
75  newsize = fSize*2;
76  QVector deltaResponsez(newsize);
77  QVectorView deltaResponsez_first(deltaResponsez,0,fSize);
78  QVectorView deltaResponsez_second(deltaResponsez,fSize,newsize-fSize);
79  deltaResponsez_first.GetVector() = fDeltaResponse;
80  deltaResponsez_second.GetVector().Initialize(0.);
81  fDeltaResponse = deltaResponsez;
82  QRealComplexFFT transformer2(newsize);
84  }
85 
86  // analyitical formula
87  fAN = 3;
88  fAp = new double[fAN];
89  fAq = new double[fAN];
90  fAtheta = new double[fAN];
91  fAphi = new double[fAN];
92 
93  fAtheta[0] = 4.248359395863364;
94  fAphi[0] = 0.8675096732313656;
95  fAp[0] = 10.959228792517152;
96  fAq[0] = 39.425157113160175;
97  fAtheta[1] = 3.735708356325815;
98  fAphi[1] = 2.6262723114471256;
99  fAp[1] = -14.126767991748853;
100  fAq[1] = -12.701164165560234;
101  fAtheta[2] = 2.5159322478108215;
102  fAphi[2] = 4.492672953653942;
103  fAp[2] = 3.1675391992317308;
104  fAq[2] = 0.2024589840416812;
105 }
106 
107 
108 double BesselTransformer::GetDeltaResponse(double t) const
109 {
110  double result = 0.;
111  double omz = fNormCutFreq*2*M_PI;
112  for(size_t k = 0; k < fAN; k++) {
113  double tmp = 0.;
114  tmp += fAp[k] * cos(fAphi[k]*omz*t);
115  tmp += fAq[k] * sin(fAphi[k]*omz*t);
116  tmp *= exp(-fAtheta[k]*omz*t);
117  result += tmp;
118  }
119  result *= 2*omz;
120  return result;
121 }
122 
123 
124 
125 double BesselTransformer::GetExpResponse(double t_0, double tau, double t) const
126 {
127  if(t <= t_0) return 0;
128  double omz = fNormCutFreq*2*M_PI;
129  double zs = t - t_0;
130  double result = 0.;
131  for(size_t k = 0; k < fAN; k++) {
132  double c = fAphi[k] * omz;
133  double &p = fAp[k];
134  double &q = fAq[k];
135  double alpha = -fAtheta[k] * omz;
136  double alphatau = alpha - 1./tau;
137  double sina = sin(c*zs)*(p*c + q*alphatau);
138  double cosa = cos(c*zs)*(p*alphatau - q*c);
139  double sx = exp(zs*alphatau)*(sina + cosa);
140  double dx = q*c - p*alphatau;
141  result += (sx + dx) / (c*c + alphatau*alphatau);
142  }
143  result *= 2*omz * exp((t-t_0)/tau);
144 
145  return result;
146 }
147 
148 QError BesselTransformer::ConvolveTD(const QVector& pulse, int t_min, QVector& signal)
149 {
150 
151  if(pulse.Size() != fSize) return QERR_SIZE_NOT_MATCH;
152  signal.Resize(fSize);
153  // MV FIXME
154  size_t t_g_max = fSize - 1;;
155  size_t t_g_min = 0;
156  for(unsigned int t = 0; t < fSize; t++) {
157  int t_max = fSize;
158  int t_inf,t_sup;
159 
160  if(t< t_min + t_g_min) {continue;}
161  else if (t >= t_g_min + t_min && t< t_min + t_g_max) {
162  t_inf = t_min;
163  t_sup = t - t_g_min;
164  } else if (t>= t_min + t_g_max && t <= t_g_min + t_max) {
165  t_inf = t - t_g_max;
166  t_sup = t - t_g_min;
167 
168  } else if (t > t_g_min + t_max && t <= t_max + t_g_max) {
169  t_inf = t - t_g_max;
170  t_sup = t_max;
171  } else continue;
172  double fc = 0.;
173  for(int m = t_inf; m <= t_sup; m++) {
174  fc += pulse[m]*fDeltaResponse[t-m];
175  }
176  signal[t] = fc;
177  }
178  return QERR_SUCCESS;
179 }
180 
182 {
183  size_t index = (size_t)roundl(double((*t)*fConvolvedVectorTD.Size())/fDuration);
184  double ret = fConvolvedVectorTD[index];
185  return ret;
186 }
187 
189 {
190  int index = (size_t)roundl(double((*t)*fConvolvedVectorFD.Size())/fDuration);
191 // if(index < 0) return fConvolvedVectorFD[0];
192 // if(index >= (int)fSize) return fConvolvedVectorFD[fSize-1];
193 
194  return fConvolvedVectorFD[index];
195 }
196 
197 void BesselTransformer::ConvolveTD(double (*pulse)(double*))
198 {
199  QVector pulseVec(fSize);
200  for(size_t i = 0; i < fSize; i++) {
201  double convT = double(i)/fSamplingFrequency;
202  pulseVec[i] = (*pulse)(&convT);
203  }
204  ConvolveTD(pulseVec,fConvolvedVectorTD);
205 }
206 
207 void BesselTransformer::ConvolveFD(double (*pulse)(double*))
208 {
209  QVector pulseVec(fSize);
210  for(size_t i = 0; i < fSize; i++) {
211  double convT = double(i)/fSamplingFrequency;
212  pulseVec[i] = (*pulse)(&convT);
213  }
214  ConvolveFD(pulseVec,fConvolvedVectorFD);
215 }
216 
217 #ifndef __CINT__
218 void BesselTransformer::ConvolveTD(pt2FuncParam func,double* param)
219 {
220  QVector pulseVec(fSize);
221  for(size_t i = 0; i < fSize; i++) {
222  double convT = double(i)/fSamplingFrequency;
223  pulseVec[i] = (*func)(&convT,param);
224  }
225  ConvolveTD(pulseVec,fConvolvedVectorTD);
226 }
227 
228 
229 void BesselTransformer::ConvolveFD(pt2FuncParam func,double* param)
230 {
231  QVector pulseVec(fSize);
232  for(size_t i = 0; i < fSize; i++) {
233  double convT = double(i)/fSamplingFrequency;
234  pulseVec[i] = (*func)(&convT,param);
235  }
236  ConvolveFD(pulseVec,fConvolvedVectorFD);
237 }
238 
239 #endif
240 
241 QError BesselTransformer::ConvolveFD(const QVector& pulse, QVector& signal)
242 {
243  if(pulse.Size() != fSize) return QERR_SIZE_NOT_MATCH;
244 
245  if(fZeroPad) {
246  size_t newsize = 2;
247  while(newsize < fSize) {
248  newsize *=2;
249  }
250  newsize = fSize*2;
251  QVector pulsez(newsize);
252  QVectorView pulsez_first(pulsez, 0, newsize-fSize);
253  QVectorView pulsez_second(pulsez, newsize-fSize, fSize);
254  pulsez_first.GetVector().Initialize(pulse[0]);
255  pulsez_second.GetVector() = pulse;
256 
257  QRealComplexFFT transformer(newsize);
258  QVectorC pulseFD;
259  transformer.TransformToFreq(pulsez, pulseFD);
260  QVectorC convolved = pulseFD.Mult(fTransferFunction);
261  //QVectorC convolved = pulseFD;
262  QVector signalz(newsize);
263  transformer.TransformFromFreq(convolved, signalz);
264 
265  QVectorView signalz_second(signalz, newsize-fSize, fSize);
266  signal = signalz_second.GetVector();
267  } else {
268  QRealComplexFFT transformer(fSize);
269  QVectorC pulseFD;
270  transformer.TransformToFreq(pulse, pulseFD);
271  QVectorC convolved = pulseFD.Mult(fTransferFunction);
272  transformer.TransformFromFreq(convolved, signal);
273  }
274  return QERR_SUCCESS;
275 }
Diana::QComplex pow(const Diana::QComplex &z, double a)
Raise a complex number to a real power.
Definition: QComplex.cc:246
@ QERR_SIZE_NOT_MATCH
Definition: QError.hh:31
@ QERR_SUCCESS
Definition: QError.hh:27
Diana::QVector sin(const Diana::QVector &v)
Definition: QVector.cc:815
Diana::QVector cos(const Diana::QVector &v)
Definition: QVector.cc:821
Diana::QVector exp(const Diana::QVector &v)
Definition: QVector.cc:833
double GetExpResponse(double t_0, double tau, double t) const
Get analytical Response function to exponential in time domain.
void ConvolveFD(pt2FuncParam, double *param)
BesselTransformer(double cutFreq, double duration, double samplFreq, double tauRC, bool zeroPad)
constructor
double ConvolvedFuncTD(double *t)
double ConvolvedFuncFD(double *t)
QError ConvolveTD(const QVector &pulse, int t_min, QVector &signal)
Get time domain convolved vector
const QVector & GetDeltaResponse() const
Get sampled Response function in time domain.
error class with error type and description
Definition: QError.hh:115
Wrapper for a specific QRealComplexFFT algorithm class.
virtual int TransformFromFreq(const QVectorC &FT, QVector &spectrum, bool compress=false)
transform from the frequencies to the times
virtual int TransformToFreq(const QVector &data, QVectorC &FFT, bool compress=false)
transform from the times to the frequencies
subview of an existing QVector, useful to operate on a QVector slice
Definition: QVectorView.hh:18
QVector & GetVector() const
Get subview QVector.
Definition: QVectorView.hh:32