Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to uniformly resample a non-uniform signal using SciPy?

I have an (x, y) signal with non-uniform sample rate in x. (The sample rate is roughly proportional to 1/x). I attempted to uniformly re-sample it using scipy.signal's resample function. From what I understand from the documentation, I could pass it the following arguments:

scipy.resample(array_of_y_values, number_of_sample_points, array_of_x_values)

and it would return the array of

[[resampled_y_values],[new_sample_points]]

I'd expect it to return an uniformly sampled data with a roughly identical form of the original, with the same minimal and maximalx value. But it doesn't:

# nu_data = [[x1, x2, ..., xn], [y1, y2, ..., yn]] 
# with x values in ascending order

length = len(nu_data[0])
resampled = sg.resample(nu_data[1], length, nu_data[0])

uniform_data = np.array([resampled[1], resampled[0]])

plt.plot(nu_data[0], nu_data[1], uniform_data[0], uniform_data[1])
plt.show()

enter image description here blue: nu_data, orange: uniform_data

It doesn't look unaltered, and the x scale have been resized too. If I try to fix the range: construct the desired uniform x values myself and use them instead, the distortion remains:

length = len(nu_data[0])
resampled = sg.resample(nu_data[1], length, nu_data[0])
delta = (nu_data[0,-1] - nu_data[0,0]) / length
new_samplepoints = np.arange(nu_data[0,0], nu_data[0,-1], delta)
uniform_data = np.array([new_samplepoints, resampled[0]])

plt.plot(nu_data[0], nu_data[1], uniform_data[0], uniform_data[1])
plt.show()

enter image description here

What is the proper way to re-sample my data uniformly, if not this?

like image 771
Neinstein Avatar asked Nov 04 '17 18:11

Neinstein


People also ask

How does Scipy signal resample work?

The resampled signal starts at the same value as x but is sampled with a spacing of len(x) / num * (spacing of x) . Because a Fourier method is used, the signal is assumed to be periodic. The data to be resampled. The number of samples in the resampled signal.

How do you resample non uniform data in Matlab?

To resample a nonuniformly sampled signal, you can call resample with a time vector input. The next example converts our original signal to a uniform 44.1 kHz rate. You can see that our resampled signal has the same shape and size as the original signal.

How do you resample a signal?

To resample a signal by a rational factor p / q , resample calls upfirdn , which conceptually performs these steps: Insert zeros to upsample the signal by p . Apply an FIR antialiasing filter to the upsampled signal. Discard samples to downsample the filtered signal by q .


1 Answers

Please look at this rough solution:

import matplotlib.pyplot as plt
from scipy import interpolate
import numpy as np

x = np.array([0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20])
y = np.exp(-x/3.0)
flinear = interpolate.interp1d(x, y)
fcubic = interpolate.interp1d(x, y, kind='cubic')

xnew = np.arange(0.001, 20, 1)
ylinear = flinear(xnew)
ycubic = fcubic(xnew)
plt.plot(x, y, 'X', xnew, ylinear, 'x', xnew, ycubic, 'o')
plt.show()

That is a bit updated example from scipy page. If you execute it, you should see something like this: enter image description here

Blue crosses are initial function, your signal with non uniform sampling distribution. And there are two results - orange x - representing linear interpolation, and green dots - cubic interpolation. Question is which option you prefer? Personally I don't like both of them, that is why I usually took 4 points and interpolate between them, then another points... to have cubic interpolation without that strange ups. That is much more work, and also I can't see doing it with scipy, so it will be slow. That is why I've asked about size of the data.

like image 149
Michał Zaborowski Avatar answered Oct 20 '22 00:10

Michał Zaborowski