Source code for spinningdiskanalyzer.imaging.analysis

"""Curve fit of cell density versus shear stress"""

from scipy.optimize import curve_fit
from matplotlib.figure import Figure
from numpy import ndarray
from numpy import linspace
from numpy import histogram
from numpy import exp
from numpy import sqrt
from numpy import power
from numpy import pi as π


[docs] def fit( distances: ndarray, n_bins: int = 21, ) -> tuple[ndarray, ndarray, ndarray, ndarray, ndarray]: """ Fits cell density to sigmoid curve. Expects the relative `distances` of the cells from the center and `n_bins`, the number of bins in the histogram. Returns `(x_data, y_data, x_fit, y_fit, parameters)`, which represent the binned data of shear stress vs. normalized cell density, the coordinates of the corresponding fit curve, and the fit parameters. """ # Create histogram. bins = linspace(0, 1, num=n_bins, endpoint=True) (counts, edges) = histogram(distances, bins) # Normalize cell density. bin_area = π * (bins[1:]**2 - bins[:-1]**2) density = counts / bin_area density = density / density[0] # Calculate midpoints of the bins. x_bins = (bins[:-1] + bins[1:]) / 2 # Convert bin position to corresponding shear stress τ. r = 9.5 # radius in mm, taken from Mariana's script ρ = 997 # buffer density in kg/m³ μ = 0.00089 # buffer viscosity in N·s/m² ω = 261.8 # velocity in radians: 104.72 dyn per 1000 rpm τ = 0.8 * r * 0.001 * sqrt(ρ * μ * power(ω, 3)) * 10 x_data = τ * x_bins y_data = density # Fit to sigmoid curve. (parameters, _) = curve_fit(sigmoid, x_data, y_data, method='dogbox') x_fit = linspace(0, x_data.max(), 100) y_fit = sigmoid(x_fit, *parameters) return (x_data, y_data, x_fit, y_fit, parameters)
[docs] def sigmoid(x: ndarray, a: float, b: float, c: float) -> ndarray: r""" Fit function according to [Boettiger (2007)]. - `a` is the plateau maximum and constrained to 0.95 < a < 1.05. - `b` is the slope of the curve at the inflection point. It reflects the distribution. - `c` is $\tau_{50}$, the mean shear stress required for cell detachment and is proportional to the number of adhesive bonds. [Boettiger (2007)]: https://doi.org/10.1016/S0076-6879(07)26001-X """ return a / (1 + exp(b * (x - c)))
[docs] def plot( figure: Figure, x_data: ndarray, y_data: ndarray, x_fit: ndarray, y_fit: ndarray, parameters: ndarray, ): """Plots binned data and fit curve onto given Matplotlib `figure`.""" (a, b, c) = parameters formula = fr'$\frac{{{a:.2f}}}{{ 1 + \exp({b:.2f} \cdot (x - {c:.2f}))}}$' axes = figure.add_subplot() axes.plot(x_data, y_data, 'o', label='data', markersize=7, color='tab:blue') axes.plot(x_fit, y_fit, '-', label=f'fit: {formula}', linewidth=2, color='tab:orange', zorder=-1) axes.set_xlabel('shear stress [dyn/cm²]') axes.set_xscale('log') axes.set_xlim(1, 10_000) axes.set_ylim(0, 1.5) axes.set_ylabel('normalized cell density') axes.legend()