0

I am trying to interpolate 3 values that I have measured, each one is related to a circular area of which I am considering the diameter (40mm, 50mm, and 100mm). I would like to interpolate them in order to find the values for 60mm, 70mm, and 80mm. The value related to the 100mm diameter must be the highest one, I don't want for example that the value at 80mm is higher than the one at 100mm. The code I use is the following:

import matplotlib.pyplot as plt
import scipy as sp
from scipy import interpolate
from matplotlib.ticker import (MaxNLocator, MultipleLocator)

# Estamte the Lagrange Interpolation for x squared based on three values
y = sp.interpolate.lagrange([40, 50, 100], [1.00132949, 1.01038226, 1.01108727])

print(y(60), y(70), y(80))


fig,axes=plt.subplots(1,1)
axes.xaxis.set_major_locator(MaxNLocator(8))
axes.yaxis.set_major_locator(MaxNLocator(8))
axes.plot([40., 50., 60., 70., 80., 90., 100.], y([40., 50., 60., 70., 80., 90., 100.]), 
linestyle='--', marker='o')
plt.xlabel(r"Applicator [mm]")
plt.ylabel(r"Output Factor")
plt.xlim(30,110)
plt.ylim(1, 1.03)
plt.title( r'Interpolazione $12\, MeV$ Applicatore $45°$')
axes.tick_params(direction='in', which='minor')
axes.tick_params(direction='in', length=4, width=1, grid_alpha=0.5)
#axes.xaxis.set_minor_locator(MultipleLocator())
axes.yaxis.set_minor_locator(MultipleLocator(0.001))
plt.legend()
plt.grid()
plt.show()

This is the plot I get for a set of values.
This is the plot I get for a set of values.

Maybe I should interpolate with a logarithmic function? How should I do that?

Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
Klari
  • 1

1 Answers1

0

Have a look at scipy.interpolate.PchipInterpolator. This will preserve monotonicity between your datapoints.

import matplotlib.pyplot as plt
import scipy as sp
import numpy as np

xs = np.linspace(40,100,100)
ys = sp.interpolate.pchip_interpolate([40, 50, 100], [1.00132949, 1.01038226, 1.01108727], x=xs)
plt.plot(xs, ys, linestyle='--')
plt.plot([40, 50, 100], [1.00132949, 1.01038226, 1.01108727], linestyle="", marker="o")
plt.show()

In general, it is not always possible to interpolate three points with a logarithm, you need to relax your problem to curve fitting here. In its most flexible form, this can be done with scipy.optimize.curve_fit. Here is a post about how to do that.

  • Unfortunately scipy.interpolate.PchipInterpolator doesn't allow me to have a smooth interpolation – Klari May 02 '22 at 12:06
  • Have you tried tuning the derivatives manually to make it "look smoother"? Also by smooth, do you mean mathematical C Infinity smoothness or does it just look choppy? – One Full Time Equivalent May 02 '22 at 12:13
  • It gives me a broken line between the points I give. What I would like is a continuous line, like the one in the plot I posted, but with the monotonicity of scipy.interpolate.PchipInterpolator – Klari May 02 '22 at 12:47
  • That is because your data is almost rectangular. You need to sample more points from the interpolator to see that it is at least C1-Smooth. – One Full Time Equivalent May 02 '22 at 13:40