3 std::map<std::pair<int, int>, fftw_plan> fRealToComplex;
4 std::map<std::pair<int, int>, fftw_plan> fComplexToReal;
5 std::map<std::pair<int, int>,
double*> fReals;
6 std::map<std::pair<int, int>, complex<double>*> fComplex;
21 std::pair<int, int> key(len, threadInd);
22 std::map<std::pair<int, int>,fftw_plan>::iterator it = fRealToComplex.find(key);
23 if(it==fRealToComplex.end()){
25 fReals[key] = (
double*) fftw_malloc(
sizeof(
double)*len);
26 fComplex[key] = (complex<double>*) fftw_malloc(
sizeof(fftw_complex)*len);
27 fRealToComplex[key] = fftw_plan_dft_r2c_1d(len,fReals[key],(fftw_complex*)fComplex[key],FFTW_MEASURE);
28 fComplexToReal[key] = fftw_plan_dft_c2r_1d(len,(fftw_complex*)fComplex[key],fReals[key],FFTW_MEASURE);
56 for(
int freqInd=0; freqInd < numFreqs; freqInd++){
57 powSpec[freqInd] = 10*TMath::Log10(powSpec[freqInd]);
60 return new TGraph(numFreqs,
getFreqArray(len, dt), powSpec);
106 const double ohms = 50;
107 double conventionNorm = 1;
111 conventionNorm = 1./len;
119 conventionNorm = 1./(len*len);
127 conventionNorm = dt/len;
131 case kPowSpecDensity:
139 conventionNorm = dt*dt;
143 case kPowSpecDensity_dBm:
151 conventionNorm = dt*dt/ohms;
156 std::cerr <<
"Invalid FancyFFTs::conventionFlag in FancyFFTs::getPowerSpectrum(int len, double* input, double dt, FancyFFTs::conventionFlag normFlag) " << std::endl;
164 doFFT(len, input,
false, threadInd);
167 std::pair<int, int> key(len, threadInd);
170 complex<double>* rawFftOutputPtr = (complex<double>*) fComplex[key];
174 double* powSpec = NULL;
176 powSpec =
new double[powSpecLen];
183 bool halfPowerNquist = (len%2)==0 ?
true :
false;
185 for(
int i=0; i<powSpecLen; i++){
188 double symmetryFactor = 2;
189 if(i==0 || (halfPowerNquist && i==powSpecLen-1)){
193 powSpec[i] = symmetryFactor*conventionNorm*(pow(std::abs(rawFftOutputPtr[i]), 2));
212 complex<double>*
FancyFFTs::doFFT(
int len,
double* input,
bool copyOutputToNewArray,
int threadInd){
213 return doFFT(len, input, NULL, copyOutputToNewArray, threadInd);
228 complex<double>*
FancyFFTs::doFFT(
int len,
double* input, complex<double>* output,
int threadInd){
229 return doFFT(len, input, output,
true, threadInd);
245 complex<double>*
FancyFFTs::doFFT(
int len,
double* input, complex<double>* output,
bool copyOutputToNewArray,
int threadInd){
251 std::pair<int, int> key(len, threadInd);
254 memcpy(fReals[key], input,
sizeof(
double)*len);
256 fftw_execute(fRealToComplex[key]);
258 if(copyOutputToNewArray==
true){
260 complex<double>* theOutput = output;
262 theOutput =
new complex<double>[numFreqs];
266 memcpy(theOutput, fComplex[key],
sizeof(fftw_complex)*numFreqs);
289 return doInvFFT(len, input, NULL, copyOutputToNewArray, threadInd);
307 return doInvFFT(len, input, output,
true, threadInd);
325 double*
FancyFFTs::doInvFFT(
int len, complex<double>* input,
double* output,
bool copyOutputToNewArray,
int threadInd){
332 std::pair<int, int> key(len, threadInd);
337 complex<double>* tempVals = (complex<double>*) fComplex[key];
342 memcpy(tempVals, input,
sizeof(fftw_complex)*numFreqs);
346 fftw_execute(fComplexToReal[key]);
349 double* invFftOutPtr = fReals[key];
350 for(
int i=0; i<len; i++){
351 invFftOutPtr[i]/=len;
354 double* theOutput = output;
355 if(copyOutputToNewArray==
true){
357 theOutput =
new double[len];
359 memcpy(theOutput, invFftOutPtr,
sizeof(
double)*len);
378 return pow(2, TMath::CeilNint(TMath::Log2(len)));
397 double df = 1./(dt*len);
398 double* freqArray =
new double[numFreq];
399 for(
int i=0; i<numFreq; i++){
400 freqArray[i] = df * i;
437 return zeroPadFFT(fft, NULL, numSamples, numSamplesUpsampled);
457 complex<double>*
FancyFFTs::zeroPadFFT(complex<double>* fft, complex<double>* output,
int numSamples,
int numSamplesUpsampled){
460 const int numFreqsPadded =
getNumFreqs(numSamplesUpsampled);
462 complex<double>* fftPadded = NULL;
464 fftPadded =
new complex<double>[numFreqsPadded];
475 Double_t scale = numSamplesUpsampled/numSamples;
477 for(
int freqInd=0; freqInd<numFreqs; freqInd++){
478 fftPadded[freqInd].real(fft[freqInd].real()*scale);
479 fftPadded[freqInd].imag(fft[freqInd].imag()*scale);
481 for(
int freqInd=numFreqs; freqInd<numFreqsPadded; freqInd++){
482 fftPadded[freqInd] = 0;
487 const Double_t sqrtHalf = TMath::Sqrt(0.5);
488 fftPadded[numFreqs-1].real(sqrtHalf*fftPadded[numFreqs-1].real());
489 fftPadded[numFreqs-1].imag(sqrtHalf*fftPadded[numFreqs-1].imag());
503 std::vector<std::pair<int, int> > keys;
505 std::map<std::pair<int, int>,fftw_plan>::iterator it;
506 for(it = fRealToComplex.begin(); it != fRealToComplex.end(); it++){
507 keys.push_back(it->first);
515 std::cout <<
"Plan lengths in memory = [";
516 for(
int i=0; i<int(keys.size()); i++){
519 std::cout <<
"(" << keys.at(i).first <<
", " << keys.at(i).second <<
")";
520 if(i <
int(keys.size())-1 ) std::cout <<
", ";
522 std::cout <<
"]" << std::endl;
524 return int(keys.size());
548 complex<double>* tempVals2 =
doFFT(len, v2,
true, threadInd);
551 doFFT(len, v1,
false, threadInd);
553 std::pair<int, int> key(len, threadInd);
556 complex<double>* tempVals1 = (complex<double>*) fComplex[key];
560 for(
int i=0; i<numFreqs; i++){
561 tempVals1[i] *= std::conj(tempVals2[i]);
567 double* crossCorr =
doInvFFT(len, tempVals1,
true, threadInd);
573 for(
int i=0; i<len; i++){
613 double* output,
int threadInd){
624 std::pair<int, int> key(len, threadInd);
627 complex<double>* tempVals = (complex<double>*) fComplex[key];
637 for(
int i=0; i<numFreqs; i++){
638 tempVals[i] = fft1[i]*std::conj(fft2[i]);
642 double* crossCorr = output;
645 crossCorr =
doInvFFT(len, tempVals,
true, threadInd);
649 crossCorr =
doInvFFT(len, tempVals, crossCorr,
true, threadInd);
657 for(
int i=0; i<len; i++){
int extendToPowerOfTwo(int len)
Find the next highest power of two.
TGraph * getPowerSpectrumTGraph(int len, double *input, double dt, conventionFlag normFlag, bool dBScale, int threadInd=0)
Creates a power spectrum TGraph from an array of doubles.
double * getPowerSpectrum(int len, double *input, double dt, conventionFlag normFlag, int threadInd=0)
Creates the power spectrum in an array of doubles of length (len/2 + 1).
complex< double > * zeroPadFFT(complex< double > *fft, int numSamples, int numSamplesUpsampled)
Zero padds FFTts,.
double * crossCorrelate(int len, double *v1, double *v2, int threadInd=0)
Cross correlates the two input arrays.
complex< double > * doFFT(int len, double *input, bool copyOutputToNewArray, int threadInd=0)
Does a forward fast fourier transform on a real input array.
int printListOfKeys()
Prints the list of keys of plans to stdout.
double * getFreqArray(int len, double dt)
Get the array of frequencies to go with FFT output, determined by the tranform length and dt...
int getNumFreqs(int len)
Get the number of frequencies from the number of samples.
bool makeNewPlanIfNeeded(int len, int threadInd=0)
Creates new fftw plan to handle 1D transforms of length len if they haven't been allocated already...
double * getRealArray(std::pair< Int_t, Int_t > key)
Get the real array of the internal fftw memory. Do not delete this!
conventionFlag
Flag to pass to FancyFFT functions specifying normalization of power spectra.
double * doInvFFT(int len, complex< double > *input, bool copyOutputToNewArray, int threadInd=0)
Does an inverse fast fourier transform on an array of complex<double>s.