'Interpolation using Lagrange not working how I want. How can I interpolate with a logarithmic function?

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?



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1