[1]:
import numpy
from matplotlib import pyplot
import ipywidgets
import calibr8
WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.
The Generalized Logistic Function
Real-world calibration curves rarely follow linear dose/response relationships, but often exhibit lower & upper saturations. These relationships can be described with S-shaped functions. The logistic function (the sigmoid curve is a special case of it) is often well suited for real-world calibration curves.
Several different flavors of S-shaped curves are available: + sigmoid (1 parameter: variable slope) + logistic (3 parameters: variable upper limit, variable x-value of the inflection point, variable slope) + generalized logistic (5 parameters: variable limits, variable inflection point, variable slope, variable symmetry)
Here, we’re going to use the generalized logistic, because it is most useful. However, we use a different parametrization that is derived in the notebook Background_AsymmetricLogistic
.
The following table shows the bounds & interpretation of its 5 paramters:
parameter |
interpretation |
---|---|
\(L_L \in \mathcal{R}\) |
lower asymptote |
\(L_U \in \mathcal{R}\) |
upper asymptote |
\(I_x \in \mathcal{R}\) |
x-value of the inflection point |
\(S \in \mathcal{R}\) |
slope at the inflection point |
\(c \in \mathcal{R}\) |
moves the inflection point closer to |
Example
Let’s say we have an assay with noticeable lower- and upper satuation limits, as well as some asymmetry.
To visualize the meaning of the parameters, we can draw an interactive plot of the calibr8.asymmetric_logistic
function:
[2]:
help(calibr8.asymmetric_logistic)
Help on function asymmetric_logistic in module calibr8.core:
asymmetric_logistic(x, theta)
5-parameter asymmetric logistic model.
Parameters
----------
x : array-like
independent variable
theta : array-like
parameters of the logistic model
L_L: lower asymptote
L_U: upper asymptote
I_x: x-value at inflection point
S: slope at the inflection point
c: symmetry parameter (0 is symmetric)
Returns
-------
y : array-like
dependent variable
[3]:
def tangent(I_x, I_y, S):
"""Get x,y to plot a line with slope S around the coordinate <I_x,I_y>."""
x = numpy.linspace(I_x-1,I_x+1,2)
y = -S*I_x + I_y + S*x
return x, y
def plot_logistic(L_L=0, L_U=1, I_x=0.0, S=0.5, c=1.0):
theta = (L_L, L_U, I_x, S, c)
X_MIN, X_MAX = -5, 5
X = numpy.linspace(-5, 5, 100)
# get key properties to visualize
I_y = calibr8.asymmetric_logistic(I_x, theta)
fig, ax = pyplot.subplots(figsize=(16,6))
ax.plot(X, calibr8.asymmetric_logistic(X, theta))
ax.plot(*tangent(I_x, I_y, S), label='$tangent$')
ax.axvline(I_x, linestyle=':', color='red', label='$I_x$')
ax.axhline(I_y, linestyle=':', color='red', label='$I_y$')
ax.axhline(L_U, linestyle=':', label='$L_U$')
ax.axhline(L_L, linestyle='--', label='$L_L$')
ax.set_xlim(X_MIN, X_MAX)
ax.set_ylim(L_L-0.5, L_U+0.5)
ax.legend(loc='center left')
pyplot.show()
plot_logistic()
ipywidgets.interact(
plot_logistic,
L_L=(-5.0,0),
L_U=(0.0,5),
I_x=(-5.0, 5),
S=(-2.0, 3),
c=(-2.0, 2)
);
Summary
The generalized logistic function can describe relationships with lower & upper satuation
Even in cases of “good linear relationships”, the GLF is applicable
The original parameterization is not very intuitive, but was reparameterized such that 4 of 5 parameters are interpretable
[4]:
%load_ext watermark
%watermark -n -u -v -iv -w
Last updated: Wed Feb 23 2022
Python implementation: CPython
Python version : 3.8.12
IPython version : 7.31.0
matplotlib: 3.5.1
sys : 3.8.12 | packaged by conda-forge | (default, Oct 12 2021, 21:22:46) [MSC v.1916 64 bit (AMD64)]
ipywidgets: 7.6.5
calibr8 : 6.4.0
numpy : 1.20.3
Watermark: 2.3.0