CONVERT FREQUENCY DOMAIN DATA TO TIME DOMAIIN

89 views (last 30 days)
ridham
ridham on 17 Jan 2026 at 9:55
Commented: ridham on 23 Jan 2026 at 3:48
i have .csv file which contains frequency (Hz), magnitude(dB), phase(degrees). these data are range from 20hz to 2000000Hz(2MHz) and these are non uniformly spaced. i want to convert these data in time domain. i have done ifft code for that. is it correct ?
% Load CSV data
data = readmatrix(filenames{file_idx});
% Extract columns (adjust indices if your CSV has different column order)
freq = data(:, 1); % Frequency in Hz
mag_dB = data(:, 2); % Magnitude in dB
phase_deg = data(:, 3); % Phase in degrees
% Convert to linear magnitude and radians
mag_linear = 10.^(mag_dB/20);
phase_rad = deg2rad(phase_deg);
% Store original data
results{file_idx}.freq_orig = freq;
results{file_idx}.mag_dB_orig = mag_dB;
results{file_idx}.phase_deg_orig = phase_deg;
% Determine frequency range
f_min = min(freq);
f_max = max(freq);
% Use power of 2 for efficient FFT
N_fft = 2^nextpow2(length(freq) * 8);
% Calculate number of positive frequency bins
n_pos = floor(N_fft/2) + 1;
% Create frequency vector for FFT bins
freq_fft_positive = linspace(f_min, f_max, n_pos);
% Interpolate magnitude and phase
mag_fft = interp1(freq, mag_linear, freq_fft_positive, 'pchip', 'extrap');
phase_fft = interp1(freq, (phase_rad), freq_fft_positive, 'pchip', 'extrap');
H_fft_pos = mag_fft .* exp(1j * phase_fft);
% Initialize full spectrum
H_full = zeros(1, N_fft);
% Place positive frequencies (DC to Nyquist)
H_full(1:n_pos) = H_fft_pos;
% Mirror for negative frequencies (conjugate symmetry)
if mod(N_fft, 2) == 0
H_full(n_pos+1:N_fft) = conj(H_fft_pos(end-1:-1:2));
else
H_full(n_pos+1:N_fft) = conj(H_fft_pos(end:-1:2));
end
% Perform IFFT
h_time = ifft(H_full, 'symmetric');
% Create time vector
fs = 2 * f_max;
dt = 1 / fs;
t = (0:N_fft-1) * dt;
  2 Comments
Star Strider
Star Strider on 17 Jan 2026 at 14:10
You can calculate the inverse Fourier transform of your frequency domain data, however I doubt that the result would be at all meaningful. There is simply too much missing information in your original data.

Sign in to comment.

Accepted Answer

Paul
Paul on 18 Jan 2026 at 21:47
Edited: Paul on 19 Jan 2026 at 14:36
Here's an example that illustrates the potential utility and pitfalls of this approach.
EDIT: 19 Jan 2026, updated code to ensure the extrapolated transform is real at f = 0
Generate time domain data
N = 100;
n = 0:N-1;
xval = (0.94.^n).*(n>=10 & n <= 30);
Plot its transform (magnitude) so we get an idea of what we are dealing with; note the large magnitude at low frequencies
Xval = fft(xval);
figure
plot(n/N,abs(Xval))
xlabel('freq');ylabel('abs');
Define the range of frequencies over which we'll have non-uniformly spaced samples of frequency domain data. For simplicity, we assume the max frequency is the Nyquist frequency.
% Nyquist frequency
fNyq = 0.5;
fmin = 0;
fmax = fNyq;
Generate frequency domain samples over random frequencies between fmin and fmax. We use N frequencies, which is what would be needed to represent the time domain signal if they were uniformly spaced.
rng(101);
fsamp = sort([0,fmax*rand(1,N-2),fmax]);
Evaluate the transform at the frequency domain samples.
Xsamp = freqz(xval,1,fsamp,1);
Overlay the random samples on the transform
hold on
plot(fsamp,abs(Xsamp),'o'),grid
Do the interpolation/extraploation and then transform back to time domain. Here, nmin defines the number of low frequency samples that we exclude (the OP stated that the data is not available down to DC). If nmin = 0, we're just interpolating fsamp as given. If nmin = 1, then we're interpoationg from fsamp(2:end) and extrapolating back to f = 0, and so on.
for nmin = 0:3
helper(n,xval,fsamp(nmin+1:end),Xsamp(nmin+1:end),nmin,fmax);
end
We see that for this data set interpolating in the frequency domain over 0-Fnyq works o.k., sort of. But as we start neglecting (high amplitude) lower frequency samples and have to extapolate down to DC the result starts to break down.
I guess the approach proposed by the OP (as modified below) might work depending on the underlying physics, but I can definitely see it being problematic. And I'm sure this all depends on how well the original frequency-domain samples capture the important parts of the transform, among who knows what other things.
Should also be able to use nufft w/o interpolation/extrapolation instead of ifft w/ interpolation/extrapolation for this type of problem.
function helper(n,xval,fsamp,Xsamp,nmin,fmax)
% define number of uniformly spaced frequency domain samples from 0 to
% sampling frequency
N2 = 512;
% define "lower half" frequency vector with uniform spacing with N2 being even
finterp = linspace(0,fmax,N2/2+1);
% linear interpolation/extrapolation of real and imaginary parts
Xinterp = interp1(fsamp,Xsamp,finterp,'linear','extrap');
% Ensure points at Nyquist and DC are real, there may be better ways to do
% this depending on data?
Xinterp(end) = real(Xinterp(end));
Xinterp(1) = abs(Xinterp(1));
% inverse transform
xinterp = ifft(Xinterp,N2,'symmetric');
% same as
% xinterp = ifft([Xinterp,fliplr(conj(Xinterp(2:end-1)))],'symmetric');
% plot
figure
n2 = 0:N2-1;
plot(n,xval,n2,xinterp),grid
legend('original','after interp/extrapolation');
title("nmin = " + double(nmin));
xlabel('n')
end
  3 Comments
Paul
Paul on 19 Jan 2026 at 15:45
Let's take a look at the frequency-domain data
data = readmatrix('frequency data.csv');
% Extract columns (adjust indices if your CSV has different column order)
freq = data(:, 1); % Frequency in Hz
mag_dB = data(:, 2); % Magnitude in dB
phase_deg = data(:, 3); % Phase in degrees
figure
plot(subplot(211),freq,mag_dB),grid
plot(subplot(212),freq,phase_deg),grid
figure
plot(diff(freq)),grid
It looks very smooth and dense, so interpolation might not be so bad. It looks flat at low frequency with zero phase, so instead of extrapolating to 0, maybe it would be better to prepend a point to the data at f = 0 with value equal to the magnitude of the first data point before interpolation.
Not sure what to make of the phase being so far away from zero (or 180) at the last data point. Maybe someone else has an idea.
Do you have any details on how the frequency-domain data was generated?

Sign in to comment.

More Answers (1)

William Rose
William Rose on 17 Jan 2026 at 14:07
I think your approach will work. You convert dB to magn, you convert degrees to radians. You convert magn, phase to real, imag. This is all good. You interpolate the unevenly spaced freqs to a linear set of freqs. You make sure the upper half of the spectrum is the conjugate mirror image of the lower half. You check if the number of freqs is even or odd and adjust as necessary. This is good. The factor of 8 which you use when allocating the vector for the complex vector must depend on your knowledge of the unevenly spaced frequencies. Since we don't have your actual data, we cannot be sure it will all work, but it looks good to me. Test it with simulated data for which you know the correct answer.
Good luck with your work.
  1 Comment
Paul
Paul on 18 Jan 2026 at 3:10
Hi William,
To the extent this approach might work at all (hard to say w/o seeing the actualy data as you said), my suggestions would be:
interpolate real and imaginary parts instead of mag and phase. If interpolating in mag and phase, at least make sure the phase is correctly unwrapped before interpolation.
I'd make sure to fill in Hfft for frequency points from 0 to fmin in H_fft_pos before going to Hfull.
Definitely test the approach with simulated data, hopefully simulated data that has characteristics similar to the actual data.

Sign in to comment.

Tags

Products


Release

R2025b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!