Diana Software
QVectorTools.cc
Go to the documentation of this file.
1 #include "QVectorTools.hh"
2 
3 #include "QRealComplexFFT.hh"
4 #include <TRandom.h>
5 #include <TMath.h>
6 #include <math.h>
7 
8 //_____________________________________________________________________________
9 Diana::QVector Diana::QVectorTools::Zeros(UInt_t size) {
10  Diana::QVector vec(size);
11  vec.Initialize(0);
12  return vec;
13 }
14 
15 //_____________________________________________________________________________
16 Diana::QVector Diana::QVectorTools::Range(UInt_t size) {
17  Diana::QVector vec(size);
18  for(UInt_t i=0;i<size;i++) vec[i]=i;
19  return vec;
20 }
21 
22 //_____________________________________________________________________________
23 Diana::QVector Diana::QVectorTools::Range(UInt_t min,UInt_t max,UInt_t stride) {
24  UInt_t NP=(max-min-1)/stride+1;
25  Diana::QVector vec(NP);
26  for(UInt_t i=0;i<NP;i++) vec[i]=min+i*stride;
27  return vec;
28 }
29 
30 //_____________________________________________________________________________
31 Diana::QVector Diana::QVectorTools::LinSpace(Double_t min,Double_t max,UInt_t size) {
32  return (max-min)*Range(size)/(size-1)+min;
33 }
34 
35 //_____________________________________________________________________________
36 Diana::QVector Diana::QVectorTools::LogSpace(Double_t min,Double_t max,UInt_t size) {
37  return pow(10.,LinSpace(min,max,size));
38 }
39 
40 //_____________________________________________________________________________
41 Diana::QVector Diana::QVectorTools::Random::Gauss(UInt_t Size,double mean,double std) {
42  Diana::QVector t(Size);
43  for(UInt_t i=0;i<Size;i++)
44  t[i] = gRandom->Gaus(mean,std);
45  return t;
46 }
47 
48 //_____________________________________________________________________________
49 Diana::QVector Diana::QVectorTools::Random::Uniform(UInt_t Size,double max) {
50  return Uniform(Size,0,max);
51 }
52 
53 //_____________________________________________________________________________
54 Diana::QVector Diana::QVectorTools::Random::Uniform(UInt_t Size,double min,double max) {
55  Diana::QVector t(Size);
56  for(UInt_t i=0;i<Size;i++)
57  t[i] = gRandom->Uniform(min,max);
58  return t;
59 }
60 
61 //_____________________________________________________________________________
62 Diana::QVector Diana::QVectorTools::Random::NoiseWaveformFromANPS(const Diana::QVector &anps) {
63 
64  const double sqrt2over2 = sqrt(0.5);
65 
66  Diana::QVector noise;
67  Diana::QVectorC noiseC(anps.Size());
68 
69  noiseC[0].Set(0,0); // Set zero DC value
70  noiseC[noiseC.Size()-1] = sqrt2over2*gRandom->Exp(sqrt(anps[noiseC.Size()-1]));
71  for(size_t i=1;i<noiseC.Size()-1;i++)
72  noiseC[i].SetPolar(sqrt2over2*gRandom->Exp(sqrt(anps[i])),
73  TMath::TwoPi()*gRandom->Uniform(0,1));
74 
76 
77  return noise;
78 }
79 
80 //_____________________________________________________________________________
81 Diana::QVector Diana::QVectorTools::Convolve(const Diana::QVector &vecA,const Diana::QVector &vecB,ConvolveReturn mode) {
82  Diana::QVector output = Zeros(vecA.Size()+vecB.Size()-1);
83  for(size_t i=0;i<output.Size();i++) {
84  for(size_t j=0;j<vecA.Size();j++) {
85  if(((int)i-(int)j)<0 || (i-j)>=vecB.Size()) continue;
86  output[i] += vecA[j]*vecB[i-j];
87  }
88  }
89  if(mode == kConvolveSame) {
90  int retSize = std::max(vecA.Size(),vecB.Size());
91  int offset = (output.Size()-retSize)/2;
92  output=output.GetSubVector(retSize,offset);
93  }
94  else if(mode == kConvolveValid) {
95  int retSize = std::max(vecA.Size(),vecB.Size())-std::min(vecA.Size(),vecB.Size())+1;
96  int offset = (output.Size()-retSize)/2;
97  output=output.GetSubVector(retSize,offset);
98  }
99  return output;
100 }
101 
102 //_____________________________________________________________________________
103 Diana::QVector Diana::QVectorTools::CircularConvolve(const Diana::QVector &vecA,const Diana::QVector &vecB) {
104  Diana::QVector output = Zeros(vecA.Size()+vecB.Size()-1);
105  const Diana::QVector &longVec = (vecA.Size() >= vecB.Size() ? vecA : vecB);
106  const Diana::QVector &shortVec = (vecA.Size() < vecB.Size() ? vecA : vecB);
107  for(size_t i=0;i<output.Size();i++) {
108  for(size_t j=0;j<shortVec.Size();j++) {
109  output[i] += shortVec[j]*longVec[(i-j+longVec.Size())%longVec.Size()];
110  }
111  }
112  return output;
113 }
114 
115 //_____________________________________________________________________________
116 Diana::QVector Diana::QVectorTools::ConvolveFFT(const Diana::QVector &vecA,const Diana::QVector &vecB,ConvolveReturn mode) {
117 
118  const Int_t SizeToOverlapAdd = 5000;
119 
120  Diana::QVectorC vecA_f,vecB_f;
121  Diana::QRealComplexFFT FFT;
122  Diana::QVector output;
123  if(std::abs((int)(vecA.Size()-vecB.Size()))<SizeToOverlapAdd) {
124  // If the sizes are very close, just pad them, fft them and add them.
125  int padSize = vecA.Size()+vecB.Size()-1;
126  Diana::QVector vecA_p = Diana::QFFT::ZeroPad(vecA,padSize-vecA.Size(),Diana::QFFT::kRight);
127  Diana::QVector vecB_p = Diana::QFFT::ZeroPad(vecB,padSize-vecB.Size(),Diana::QFFT::kRight);
128  FFT.TransformToFreq(vecA_p,vecA_f);
129  FFT.TransformToFreq(vecB_p,vecB_f);
130  Diana::QVectorC output_f = vecA_f.Mult(vecB_f);
131  FFT.TransformFromFreq(output_f,output);
132  output=output.GetSubVector(vecA.Size()+vecB.Size()-1);
133  }
134  else {
135  // if the sizes are vastly different, use the overlap and add method
136  output.Resize(vecA.Size()+vecB.Size()-1);
137  output.Initialize(0);
138 
139  const Diana::QVector &longVec = (vecA.Size() > vecB.Size() ? vecA : vecB);
140  const Diana::QVector &shortVec = (vecA.Size() < vecB.Size() ? vecA : vecB);
141 
142  UInt_t longSize = longVec.Size();
143  UInt_t shortSize = shortVec.Size();
144  UInt_t skip,dum;
145  Diana::QFFT::IsPowerOf2(shortSize,skip,dum);
146  skip=pow(2,skip);
147 
148  Diana::QVector output_seg;
149  Diana::QVector shortVec_p = Diana::QFFT::ZeroPad(shortVec,skip-1,Diana::QFFT::kRight);
150  Diana::QVectorC shortVec_f,long_seg_f,output_seg_f;
151  FFT.TransformToFreq(shortVec_p,shortVec_f);
152 
153  for(UInt_t segStart=0;segStart<longSize;segStart+=skip) {
154  if(segStart+skip<longSize) {
155  Diana::QVector long_seg_p = Diana::QFFT::ZeroPad(longVec.GetSubVector(skip,segStart),shortSize-1,Diana::QFFT::kRight);
156  FFT.TransformToFreq(long_seg_p,long_seg_f);
157  output_seg_f = long_seg_f.Mult(shortVec_f);
158  FFT.TransformFromFreq(output_seg_f,output_seg);
159  output.GetSubVector(shortSize+skip-1,segStart) += output_seg;
160  }
161  else {
162  output_seg=ConvolveFFT(shortVec,longVec.GetSubVector(longSize-segStart,segStart));
163  output.GetSubVector(output.Size()-segStart,segStart) += output_seg;
164  }
165  }
166  }
167  if(mode == kConvolveSame) {
168  int retSize = std::max(vecA.Size(),vecB.Size());
169  int offset = (output.Size()-retSize)/2;
170  output=output.GetSubVector(retSize,offset);
171  }
172  else if(mode == kConvolveValid) {
173  int retSize = std::max(vecA.Size(),vecB.Size())-std::min(vecA.Size(),vecB.Size())+1;
174  int offset = (output.Size()-retSize)/2;
175  output=output.GetSubVector(retSize,offset);
176  }
177 
178  return output;
179 }
double max
Definition: CheckOF.C:53
QVector vec(3)
Diana::QComplex pow(const Diana::QComplex &z, double a)
Raise a complex number to a real power.
Definition: QComplex.cc:246
QRealComplexFFT * gRealComplexFFT
Diana::QVector abs(const Diana::QVector &v)
Definition: QVector.cc:811
double min(const Diana::QVector &v)
Definition: QVector.cc:878
virtual int TransformFromFreq(const QVectorC &FT, QVector &spectrum, bool compress=false)
transform from the frequencies to the times
void Initialize(const double val=0)
initialize elements (default to 0)
Definition: QVector.cc:218
Diana::QVector Uniform(UInt_t Size, double max=1)
Return a uniform distributed vector of size Size.
Diana::QVector NoiseWaveformFromANPS(const Diana::QVector &anps)
Build a noise waveform from an ANPS.
Diana::QVector Gauss(UInt_t Size, double mean=0, double std=1.)
Diana::QVector LinSpace(Double_t min, Double_t max, UInt_t size)
Return a linear spaced values from min to max.
Diana::QVector LogSpace(Double_t min, Double_t max, UInt_t size)
Return a log spaced values from 10**min to 10**max.
ConvolveReturn
Return modes from convolutions.
Definition: QVectorTools.hh:45
@ kConvolveSame
Return a vector with size equal to the max of the two inputs.
Definition: QVectorTools.hh:51
@ kConvolveValid
Return only the valid samples where the two vectors fully overlap.
Definition: QVectorTools.hh:49
Diana::QVector Range(UInt_t size)
Return an indexed range from zero to size.
Diana::QVector Convolve(const Diana::QVector &vecA, const Diana::QVector &vecB, ConvolveReturn mode=kConvolveFull)
Discrete convolution.
Diana::QVector CircularConvolve(const Diana::QVector &vecA, const Diana::QVector &vecB)
Discrete circular convolution.
Diana::QVector Zeros(UInt_t size)
Return a vector of zeros.
Diana::QVector ConvolveFFT(const Diana::QVector &vecA, const Diana::QVector &vecB, ConvolveReturn mode=kConvolveFull)
Convolution using FFT.