Correct Fourier scaling and high-resolution frequency identification

I will take the data as a time history. First I assume that the x-values are equally spaced and work out the time increment and frequency increment and then plot the data.

tinc = data[[2, 1]] - data[[1, 1]];
finc = 1/(tinc Length[data]);
ListPlot[data]

Mathematica graphics

This looks like almost two cycles of a sine wave with a frequency of about 0.1 and an amplitude of 17. There is a phase of about an eighth of a cycle. I now take the Fourier transform. As the data is close to a sine wave I think it is best to select FourierParameters to reflect this. We want the amplitude of the sine wave to be readable from the spectra. I choose the parameters to be {-1,-1}. This means that should we be lucky and there is a whole number of cycles in the time interval then the peak in the spectra will be half the amplitude of the sine wave. The half comes from the fact that the spectrum has two peaks (at positive and negative frequencies which are wrapped) and that we want the peak value not the rms. (We get a Sqrt[2] from each of these factors.) Calculate the Fourier transform and the corresponding frequency values.

ft = Fourier[data[[All, 2]], FourierParameters -> {-1, -1}];
ff = Table[f, {f, 0, 1/tinc - finc, finc}];
ListLinePlot[Transpose[{ff, Abs[ft]}], PlotRange -> All]

Mathematica graphics

If we expand the range we can see that we are lucky and the peak appears to coincide with a spectral line. This is not the usual case. Normally the peak lies between two spectral values. Expanding the range...

Mathematica graphics

As we are looking for a sine wave and the number of data points is small I suggest we get most accuracy by fitting in the time domain. The Fourier transform gives us a good starting estimate of the frequency. It is essential to have this otherwise NonlinearModelFit will not work. I also include an unknown for the mean value.

nlmf = NonlinearModelFit[data, 
   a + b Cos[2 \[Pi] f t] + c Sin[2 \[Pi] f t], {a, b, c, { f, 0.1}}, 
   t];

The parameter table shows that the frequency is slightly smaller than 0.1. The standard error on the frequency shows we have about 3 figures of accuracy.

nlmf["ParameterTable"]

Mathematica graphics

We can take the best fit and regenerate the data and over-plot with the original data.

fd = Table[{t, nlmf["BestFit"]}, {t, data[[All, 1]]}];
ListLinePlot[{data, fd}]

Mathematica graphics

If we take away the fitted data we can see if there is anything else to find in the data.

diff = Transpose[{data[[All, 1]], data[[All, 2]] - fd[[All, 2]]}];
ListLinePlot[diff]

Mathematica graphics

It is tempting to see a frequency in this time history but it might be random. The best strategy here is to look again at the Fourier transform.

ftdiff = Fourier[diff[[All, 2]], FourierParameters -> {-1, -1}];
ListLinePlot[Transpose[{ff, Log[10, Abs[ftdiff]]}], 
 PlotRange -> {{0, 1/(2 tinc)}, {-4, 1}}]

Mathematica graphics

I would say this is a flattish spectrum so we have reduced the time history to a white noise process which is the best we can do.

Edit for additional calculations.

The OP wishes to find out what would be the spectral value at frequencies other than those calculated by the original Fourier transform. Let us suppose that the set of frequencies that are required have frequency increment finc1. As an example we will take finc1 = 0.012. Let the number of points in the new spectrum be 1001. Then the sample rate is equal to the frequency increment times the number of points or 12.012 and the time increment is the reciprocal of this i.e. 0.0832501.

finc1 = 0.012;
nn1 = 1001;
tinc1 = 1/(finc1 nn1)

We now calculate an new sampled time history based on the best fit sine wave we have estimated.

data1 = Table[
   a Cos[2 \[Pi] f (n - 1) tinc1] + b Sin[2 \[Pi] f (n - 1) tinc1] /. 
    nlmf["BestFitParameters"], {n, 1, nn1}]; 

If we take the Fourier transform of this we will get the spectrum at the frequencies we require. We also calculate the frequency values.

ft1 = Fourier[data1, FourierParameters -> {-1, -1}];
ff1 = Table[(n - 1) finc1, {n, 1, nn1}];   

We can now plot the spectra with the frequency increment required. I have chosen a value for the frequency increment which deliberately does not get the lucky case we had before where the peak was close to one frequency value. Now we have the typical case where the peak does not correspond to a frequency so there are spectral values for many frequencies. I have expanded the frequency range and chosen the vertical range to be similar to the first spectrum. The actual best fit amplitude is 15.4995 with our spectral scaling being half of this value. We can see how misleading a spectrum can be when the frequency increment does not coincide with the frequency of the time history.

ListPlot[Transpose[{ff1, Abs[ft1]}][[1 ;; 30]], PlotRange -> {All, {0, 8}}]

Mathematica graphics

I hope I have understood what the OP wanted. There may be some confusion over the use of the word amplitude. The best fit sine wave has an amplitude and we then have ordinates of the time history and ordinates of the spectrum.


For a set of data $\{t_i,A(t)\}$ its possible to define a continuous function, properly scaled, that is the Fourier transform of the data set.

1/Sqrt[n] Sum[y[[r]] Exp[(2 π I)/n (r - 1) (s n dt)], {r, n}]

Then an implementation for the absolute value of the Fourier transform could be:

cxyFtM[d_, s_] := Block[{n, t, y, dt},
  n = Length[d];
  t = d[[All, 1]];
  y = d[[All, 2]];
  dt = Mean[Differences[t]];
  Abs[1/Sqrt[n] Sum[y[[r]] Exp[(2 π I)/n (r - 1) (s n dt)], {r, n}]]
  ]

Let's define some data

ListPlot[testdat = Rest@Table[{t, Sin[1.25 2 π t] + Sin[0.25 2 π t]}, {t, 0, 10., 1/20}]]

Mathematica graphics

Now we can compare the continuous and discrete results

Show[
 Plot[cxyFtM[testdat, s], {s, 0, 2}, PlotPoints -> 100, 
  PlotRange -> {{0, 2}, {0, 10}}],
 ListPlot[xyF[testdat], PlotStyle -> Red]
 , Epilog -> {Line[{{0.25, 0}, {0.25, 10}}], 
   Line[{{1.25, 0}, {1.25, 10}}]}
 , Frame -> True
 ]

Mathematica graphics

Amplitude is available at any arbitrary frequency, peak position now can be calculated analytically, independently of number of data points.

The estimation of the first peak, a frequency close to zero, is imperfect, but the second peak is bang on. We also see that the discrete estimation of the spectrum between the two main peaks is artificially high.

No intention to diminish the excellent answer by Hugh, just wanted to leave this other approach documented.