Posts: 30
Threads: 8
Joined: Oct 2025
Hello,
So I am using the below original code (code 1) to display a graph (graph 1), but the output is a bit course, so I have chosen to use the interpolate function to smooth it out. However when I use this smoothing function (code 2), I get the below (output) error. From this error I understand it wont compute because the x_values array is loaded (22 -> 10), instead of (10 -> 22).
I have tried doing a third version of the code (code 3) and (graph 2), that reverses x_values at the start (10 -> 22) and then reversing the x_values array using (xnew[::-1]), but the out of the graph (graph 2) looks completely wrong.
I seem to be making hard work of this interpolate function. Can you advise how I can modify my code to smooth out (graph 1)?
Thanks,
Tuurbo46
Code 1:
x_values = np.array([22, 20, 17, 16, 15, 12, 10]) # dB
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100]) # %
plt.yscale('log')
plt.ylabel("%")
plt.xlabel("dB")
plt.plot(x_values, y_values)
plt.show()Code 2:
x_values = np.array([22, 20, 17, 16, 15, 12, 10]) # dB
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100]) # %
plt.yscale('log')
plt.ylabel("%")
plt.xlabel("dB")
xnew = np.linspace(x_values.min(), x_values.max(), 100)
spl = make_interp_spline(x_values, y_values, k=3)
power_smooth = spl(xnew)
plt.plot(xnew, power_smooth)
plt.show()Output: raise ValueError("Expect x to be a 1D strictly increasing sequence.")
ValueError: Expect x to be a 1D strictly increasing sequence.
Code 3:
x_values = np.array([10, 12, 15, 16, 17, 20, 22]) # dB
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100]) # %
plt.yscale('log')
plt.ylabel("%")
plt.xlabel("dB")
xnew = np.linspace(x_values.min(), x_values.max(), 100)
xnew[::-1]
spl = make_interp_spline(x_values, y_values, k=3)
power_smooth = spl(xnew)
plt.plot(xnew, power_smooth)
plt.show()
Attached Files
Thumbnail(s)
Posts: 6,981
Threads: 22
Joined: Feb 2020
What is the value you are plotting? What do the x and y axis represent? % and DB are both units I expect to see for the vertical (Y) axis, so they don't provide any clue. Both arrays are monotonic, so that doesn't provide a clue either.
Posts: 30
Threads: 8
Joined: Oct 2025
Nov-17-2025, 09:03 AM
(This post was last modified: Nov-17-2025, 09:04 AM by Tuurbo46.)
Hello deanhystad,
I am plotting data from a power meter (I can visually see the graph and data on the power meter, but I would like to view this graph in my Python GUI). To confirm the graph details are correct, I am manually populating the graph with the below points. However, when I use the interpolate function, the data in the graph gets mixed up. Can you advise how I can modify so the interpolate display correctly?
Thanks,
Tuurbo46
x_values = np.array([22, 20, 17, 16, 15, 12, 10]) # dB
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100]) # % (10) - Power level (power to average power ratio) that has 100 % of the power (in dB)
(12) - Power level (power to average power ratio) that has 10 % of the power (in dB)
(15) - Power level (power to average power ratio) that has 1 % of the power (in dB)
(16) - Power level (power to average power ratio) that has 0.1 % of the power (in dB)
(17) - Power level (power to average power ratio) that has 0.01 % of the power (in dB)
(20) - Power level (power to average power ratio) that has 0.001 % of the power (in dB)
(22) - Power level (power to average power ratio) that has 0.0001 % of the power (in dB)
Posts: 6,981
Threads: 22
Joined: Feb 2020
Nov-19-2025, 08:34 PM
(This post was last modified: Nov-19-2025, 08:34 PM by deanhystad.)
Your previous post did not add much to my understanding of what you are trying to plot. If I sound ignorant it is because I am.
I think you have your x and y axis mixed up. I think your y_values are invariant, and the x_values are what you measure with the power meter. You can plot db and % on whatever axis you want, but for purposes of interpolation, the y values are the one that you measure, and the x values are when (or at what level) you measure. To smooth out a noisy sine wave my x values would be time (uniformly distributed time) and the y values are the amplitude. I swapped the order used to pass x and y values to the make_interp_spline function and the resulting spline does a good job reproducing the original data. Run this program and the two plots are right on top of each other.
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import make_interp_spline
x_values = np.array([22, 20, 17, 16, 15, 12, 10])
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100])
plt.yscale("log")
plt.ylabel("%")
plt.xlabel("dB")
plt.xlim(0, 22)
spline = make_interp_spline(y_values, x_values, k=3)
plt.plot(x_values, y_values)
plt.plot(spline(x_values), x_values)
plt.show(But something funny happens if I interpolate different x values.
x_values = np.array([22, 20, 17, 16, 15, 12, 10]) # dB
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100]) # %
plt.yscale("log")
plt.ylabel("%")
plt.xlabel("dB")
plt.xlim(0, 22)
spline = make_interp_spline(y_values, x_values, k=3)
plt.plot(x_values, y_values)
fine_y = np.linspace(0.0001, 100, 10000)
plt.plot(spline(fine_y), fine_y)
plt.show()The blot stats to go wonky around x = 0.01 and is wildly out of control by x = 90. Our spline doesn't have enough input points to compute a polynomial that looks like it fits the data.
This makes me start to wonder if splines or smoothing of any type is valid for this data. You have discreet data points that are essentially chosen at random. How can we take these points and make an educated guess about what the other points might be. Maybe interpolation is the wrong tool.
To test, I use linear interpolation to create 100 points from the data you provided. I plot the interpolated data against the original data.
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import make_interp_spline
def interpolate(x, x_values, y_values):
for a, b, c, d in zip(x_values, x_values[1:], y_values, y_values[1:]):
if a <= x <= b:
break
return (x - a) * (d - c) / (b - a) + c
x_values = np.array([22, 20, 17, 16, 15, 12, 10])
y_values = np.array([0.0001, 0.001, 0.01, 0.1, 1, 10, 100])
plt.yscale("log") # Comment out to view plot on linear scale.
plt.ylabel("%")
plt.xlabel("dB")
y_fine = np.logspace(-4, 2, 100)
x_fine = [interpolate(y, y_values, x_values) for y in y_fine]
plt.plot(x_values, y_values)
plt.plot(x_fine, y_fine)
plt.show()The interpolated plot looks great when yscale is linear, but looks bumpy when plotted on a log scale. Does this mean that x = 11 is a bad guess for the value at y = 55? 11 is half-way between 10 and 12, and 55 is half-way between 10 and 100, but (11, 55) is way off a line drawn between (12, 10) and (10, 100) when the y axis is log instead of linear. Maybe it isn't interpolation that's the bad choice. Maybe the problem is using a line plot to represent something that is not a line.
If you don't mind lying about your data and you want a smooth line. You can interplate your spline in log scale. Here I use -4, -3, -2, -1, 0, 1, 2 in place of the percentages. Now the datapoints are evenly spaced and make_interp_spline can do a better job fitting the data. Too complete the illusion, replace the x axis tick mark labels with 0.0001, 0.001...
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import make_interp_spline
x_values = np.array([22, 20, 17, 16, 15, 12, 10])
y_values = np.array([-4, -3, -2, -1, 0, 1, 2])
spline = make_interp_spline(y_values, x_values, k=2)
y_fine = np.linspace(-4, 2, 100, endpoint=True)
x_fine = spline(y_fine)
plt.ylabel("%")
plt.xlabel("dB")
plt.plot(x_values, y_values)
plt.plot(x_fine, y_fine)
plt.show()
|