First point in FID should be divided by 2?

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.

  1. When converting FID to spectrum, it first multiplies the first point in FID by 0.5
  2. It divides the result of fftshift(fft(fid)) by numel(fid) (suppose fid 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.)

Scaling down the first point by 0.5 prior to the discrete Fourier transform is routine in NMR data processing. Unlike other points in the FID, the first point (t=0) represents the signal averaged over a time period from -dwell time/2 to +dwell time/2. If using FFT without scaling down the first point, this overweighting will result in baseline distortions in the spectrum.
However, for in-vivo MRS, baseline distortions can arise from multiple sources beyond this DFT consideration: long deadtime (especially for X-nuclei), corrupted first FID points due to imperfect hardware, pulse sequence timing, etc. Therefore, don’t be surprised if the baseline remains distorted after applying the 0.5 scaling factor to the first point.

2 Likes