Hi folks,
I noticed that in OXSA, they don’t use the naive fft
and ifft
to convert between FID and spectrum. Instead, they have specFft
and specInvFft
. Those two functions are not long, so I post the code below.
function [spec] = specFft(fid,dim)
% FFT for spectroscopy. Converts fid --> spectrum.
%
% Accounts correctly for the 0.5x weighting for the t=0 FID point arising
% from the one-sided definition of the Fourier Transform relations in
% spectroscopy.
%
% Optional parameter: dim is the dimension to be FFT'd. Default is 1.
%
% EXAMPLE:
% zz=randn(2048,1)+1i*randn(2048,1);maxdiff(zz,specFft(specInvFft(zz)))
% OR
% zz=randn(2048,128)+1i*randn(2048,128);maxdiff(zz,specFft(specInvFft(zz)));maxdiff(zz,specFft(specInvFft(zz,2),2))
if nargin<2
dim = 1;
end
perm = [dim 1:(dim-1) (dim+1):numel(size(fid))];
% Re-use variable name "spec" to economise on RAM.
spec = permute(fid,perm);
% t=0 point is treated differently by convention for a FID
spec(1,:) = spec(1,:) * 0.5;
spec = ipermute(fftshift(fft(spec,[],1),1)/size(spec,1),perm);
function [fid] = specInvFft(spec,dim)
% Inverse FFT for spectroscopy. Converts spectrum --> fid.
%
% Accounts correctly for the 0.5x weighting for the t=0 FID point arising
% from the one-sided definition of the Fourier Transform relations in
% spectroscopy.
%
% Optional parameter: dim is the dimension to be FFT'd. Default is 1.
%
% EXAMPLE:
% zz=randn(2048,1)+1i*randn(2048,1);maxdiff(zz,specFft(specInvFft(zz)))
% OR
% zz=randn(2048,128)+1i*randn(2048,128);maxdiff(zz,specFft(specInvFft(zz)));maxdiff(zz,specFft(specInvFft(zz,2),2))
if nargin<2
dim = 1;
end
fid = ifft(fftshift(spec,dim),[],dim)*size(spec,dim);
perm = [dim 1:(dim-1) (dim+1):numel(size(fid))];
% Re-use variable name "fid" to economise on RAM.
fid = permute(fid,perm);
% t=0 point is treated differently by convention for a FID
fid(1,:) = 2*fid(1,:);
fid = ipermute(fid,perm);
I think these two functions basically do two things different from the naive fft
and ifft
.
- When converting FID to spectrum, it first multiplies the first point in FID by 0.5
- It divides the result of
fftshift(fft(fid))
bynumel(fid)
(supposefid
is a vector)
I understand that, the second difference only makes the result scale by numel(fid)
or 1/numel(fid)
My question is, why multiplying the first point in FID by 0.5? What’s the consequence if I simply use the naive fft
and ifft
? Or in other words, in practice, does it make a significant difference?
(Plus, I think in specInvFft
, the line fid = ifft(fftshift(spec,dim),[],dim)*size(spec,dim);
should use ifftshift
instead of fftshift
, in case numel(fid)
is an odd number.)