Attempting FFT with variable time between samples

Good day.

I am currently trying to take the FFT of a data set to look at the frequencies present in a data set.

Following the tutorial at https://root.cern.ch/doc/master/FFT_8C.html, an TH1 object or an array can be used to hold the data to be analyzed:

// Data array - same transform
// ===========================
   //Allocate an array big enough to hold the transform output
   //Transform output in 1d contains, for a transform of size N,
   //N/2+1 complex numbers, i.e. 2*(N/2+1) real numbers
   //our transform is of size n+1, because the histogram has n+1 bins
   Double_t *in = new Double_t[2*((n+1)/2+1)];
   Double_t re_2,im_2;
   for (Int_t i=0; i<=n; i++){
      x = (Double_t(i)/n)*(4*TMath::Pi());
      in[i] =  fsin->Eval(x);
   }
   //Make our own TVirtualFFT object (using option "K")
   //Third parameter (option) consists of 3 parts:
   //- transform type:
   // real input/complex output in our case
   //- transform flag:
   // the amount of time spent in planning
   // the transform (see TVirtualFFT class description)
   //- to create a new TVirtualFFT object (option "K") or use the global (default)
   Int_t n_size = n+1;
   TVirtualFFT *fft_own = TVirtualFFT::FFT(1, &n_size, "R2C ES K");
   if (!fft_own) return;
   fft_own->SetPoints(in);
   fft_own->Transform();

The data input section of the analysis code, fft_own->SetPoints(in);, doesn’t seem to have the capacity to accept timing information for points, so it seems like it is assuming all the points are evenly spaced in time which is not the case for my data. For the DAQ that was used data was taken for 49 equal width time bins, then there was a delay during data readout from the DAQ which was not an integer multiple of the time bin width.

Is there a way to handle this in Root’s FFT functions?

I think you should resample your time series uniformly, perhaps using Eval(x) as you do above. FFT algorithms such as Cooley-Turkey, if not all FFT algorithms, assume the discrete Fourier transform (DFT) has uniformly sampled time steps.

Unlike the code sample above I can’t resample the time series as I am working with experimental data. The times are already set.

Since stitching groups of 49 time bins together into one long series seems to be out due to the variable time interval between samples, is there accepted way to analyze each group separately, and the combine the results of the individual FFT transformation?

By resample, what I mean to say is that you can take your array of experimental data, then create another array of same length which corresponds to the experimental data being interpolated at uniform time steps.

For example, suppose I have a pointer to a TGraph of the experimental data, TGraph * grInPtr . Denoting

double * NIn = grInPtr -> GetN();
double * XIn = grInPtr -> GetX();
double * YIn = grInPtr -> GetY();

I can then create a function function corresponding to YIn, TF1 fIn:

TF1 fIn("fIn", [&](double * x, double *) {return grInPtr -> Eval(x[0]);}, XIn[0], XIn[NIn - 1], 0);
fIn.SetNpx(NIn);
fIn.SetLineColor(1);
fIn.SetLineWidth(1);

The line fIn.SetNpx(NIn) assures that if you were to copy fIn into a TGraph, the length of that TGraph is also NIn, as opposed to the default of length of 100 bins. The arguments XIn[0], XIn[NIn - 1] inside the definition of means you want to start the sampling at XIn[0] and ending at XIn[NIn - 1]. With fIn.SetNpx(NIn), the step sizes are uniform at (XIn[NIn - 1] - Xin[0]) / (NIn - 1).

One thing to be aware of is that Eval uses linear interpolation, by default. Depending on your data, you may want to use a different interpolation scheme like splining (see the TSpline class reference for more information).

Thank you for taking the time to explain the method and implementation in such detail.

That could be useful, I will look into how it works with my data.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.