Different results when computing integral analytically/with scipy VS approximating integral

Question:

I’m trying to calculate the integral of a variant of the Hill Equation shown here. enter image description here

When I try implementing this with the integrate function in SciPy, I get the following:

from scipy import integrate

Top = 0.9015038230670139
Bottom = 0.5972679490151096
ic50 = 17561.998143066336
Coef = -1.245569789770613

def Hill_formula(X):
    return Bottom + (Top - Bottom)/(1 + ((10**np.log10(ic50))/10**X)**Coef)

integrate.quad(Hill_formula, 0.001, 40.0)

with the result coming out to (25.18116866489653, 1.3873362345430754e-08)

However, looking at the graph of this equation with 100 evenly spaced points from 0.001 to 40.0, it clearly looks nothing close to the given answer of ~25: (EDIT: It actually does look right on hindsight because I misread the y-axis of the plot. Still would appreciate help on why this discrepancy exists though) enter image description here

Checking with an approximation method for the area under the curve gives a similar result:

from scipy.integrate import simpson
points = np.linspace(0.001, 40.0, num=100)
curve_results = []
for val in points:
    curve_results.append(Hill_formula(val))

np.abs(simpson(points, curve_results))

resulting in 1.2913519756923537. Is there a reason why this discrepancy exists?

I tried calculating the analytical solution of the integral and using that resulting equation to directly obtain the area under the curve between the bounds, but ran into that same strange ~25 answer.

Asked By: sharkbirth

||

Answers:

From the documentation of scipy.simpson:

scipy.integrate.simpson(y, x=None, dx=1.0, axis=-1, even='avg')

Integrate y(x) using samples along the given axis and the composite
Simpson's rule. If x is None, spacing of dx is assumed.

If there are an even number of samples, N, then there are an odd
number of intervals (N-1), but Simpson's rule requires an even number
of intervals. The parameter 'even' controls how this is handled.

Parameters
----------
y : array_like
    Array to be integrated.
x : array_like, optional
    If given, the points at which `y` is sampled.
...

That means that you’ve probably meant to write simpson(curve_results, points) instead of np.abs(simpson(points, curve_results)). That results in 25.18116860801739, which has the same first 9 digits as the one you’ve obtained and the the analytical result evaluating to 25.181168664896531....

Answered By: fiktor