Source code for cytocalc.microrheology

""" Functions for extracting viscoelasticity from microrheology measurements """

from derivative import dxdt
import numpy as np
import numpy.typing as npt


[docs] def msd_to_g_star(times: npt.NDArray[float], msd: npt.NDArray[float], radius: float, viscosity: float = 0, method: str = "evans", **kwargs) -> (npt.NDArray[float], npt.NDArray[complex]): """ Extracts Complex Shear Modulus G* (in Pa) from the MSD of a probe. Mason's method: Approximate G* using a truncated power-law expansion. Ref: :func:`_msd_to_g_star_mason` 1. Mason, T. G. Estimating the viscoelastic moduli of complex fluids using the generalized Stokes–Einstein equation. Rheol. Acta 39, 371–378 (2000). Evans' method: Extract G* using a DTFT on the creep compliance J(t). Ref: :func:`_msd_to_g_star_mason` 2. Evans, R. M. L., Tassieri, M., Auhl, D. & Waigh, T. A. Direct conversion of rheological compliance measurements into storage and loss moduli. Phys. Rev. E 80, 012501 (2009). :param times: npt.NDArray[float], an array of timepoints (unit: s) :param msd: npt.NDArray[float], an array of MSD values (unit: um^2) :param radius: float, radius of the bead (unit: um) :param viscosity: (for Evans' method only) float, viscosity of medium (unit: pN.s/um^2) :param method: str, method to use for extracting G*. Must be one of ["evans", "mason"] :returns: npt.NDArray[float], npt.NDArray[complex], an array of omegas (unit: Hz), an array of G* (G' + iG'') (unit: Pa) """ match method: case "evans": omegas, g_star = _msd_to_g_star_evans(times, msd, radius, viscosity, **kwargs) case "mason": omegas, g_star = _msd_to_g_star_mason(times, msd, radius, **kwargs) case _: raise ValueError("Method Unknown: Failed to convert MSD to G*") return omegas, g_star
[docs] def _msd_to_g_star_evans(times: npt.NDArray[float], msd: npt.NDArray[float], radius: float, viscosity: float = 0, **kwargs) -> (npt.NDArray[float], npt.NDArray[complex]): """ Extract G* from MSD using Evans' method """ omegas = [] g_star = [] raise NotImplementedError("Evans Method: To be Implemented") return omegas, g_star
[docs] def _msd_to_g_star_mason(times: npt.NDArray[float], msd: npt.NDArray[float], radius: float, **kwargs) -> (npt.NDArray[float], npt.NDArray[complex]): """ Extract G* from MSD using Mason's method 1. Mason, T. G. Estimating the viscoelastic moduli of complex fluids using the generalized Stokes–Einstein equation. Rheol. Acta 39, 371–378 (2000). """ # remove entries where time <= 0 # Mason's method does 1/t and negative # frequencies are un-physical msd = msd[np.where(times > 0)] times = times[times > 0] omegas = 1/times log_times = np.log(times) log_msd = np.log(msd) def gamma(alpha): # from [1] return 0.457*np.power((1+alpha),2) - 1.36*(1+alpha) + 1.9 # TO-DO: Possibly allow tuning of dxdt parameters? Currently chosen to match previous # hand-rolled derivative calculation alphas = dxdt(log_msd, log_times, kind="savitzky_golay", left=0.5, right=0.5, order=2) g_elastic = 0.0042*np.cos(np.pi*alphas/2) / (np.pi * radius * msd * gamma(alphas)) g_viscous = 0.0042*np.sin(np.pi*alphas/2) / (np.pi * radius * msd * gamma(alphas)) g_star = g_elastic + 1j*g_viscous return omegas, g_star