Source code for sl2pm.models

## Formulas for expected distributions of fluorescence on images/line-scans
## needed for tracking QDs, RBCs, and blood vessels 

import numpy as np
from scipy.special import erf, erfcx

###-------------------------------------------------------------------
###------------------------Quantum dots-------------------------------
[docs] def qd_blurred(x, y, b, A, xo, yo, sx, sy, theta): """ 2D rotationally-asymmetric Gaussian. This function is fitted to images of nanoparticles with MLE to estimate the nanoparticle's positions. """ b, A, sx, sy = np.abs(b), np.abs(A), np.abs(sx), np.abs(sy) dx, dy = x - xo, y - yo Q11 = np.cos(theta)**2/sx**2 + np.sin(theta)**2/sy**2 Q22 = np.sin(theta)**2/sx**2 + np.cos(theta)**2/sy**2 Q12 = 0.5*(np.sin(2*theta)/sx**2 - np.sin(2*theta)/sy**2) detQ = Q11*Q22 - Q12**2 amp = 0.5*A*np.sqrt(detQ)/np.pi expr = b + amp*np.exp(-0.5*(Q11*dx**2 + 2*Q12*dx*dy + Q22*dy**2)) return expr
###------------------------------------------------------------------- ###---------------------------RBCs------------------------------------
[docs] def rbc(x, b, A, s, xo): """ Line fluorescence intensity distribution along a RBC/plasma interface. """ return b + 0.5*A*(1 + erf((x - xo)/(np.sqrt(2)*s)))
[docs] def rbc_inv(x, b, A, s, xo): """ Line fluorescence intensity distribution along a plasma/RBC interface. """ return b + 0.5*A*(1 - erf((x - xo)/(np.sqrt(2)*s)))
###------------------------------------------------------------------- ###-----------------------Blood vessels-------------------------------
[docs] def gaussian(x, sigma): """ Gaussian distribution with zero expected value and STD=sigma. """ return np.exp(-x**2/(2*sigma**2))/np.sqrt(2*np.pi*sigma**2)
[docs] def laplace(x, l): """ Laplace distribution. """ return np.exp(-np.abs(x)/l)/(2*l)
[docs] def f_wall(x_psf, s_xy, l, R_wall, a1, n_phi=256): """ Part of the expression for L_wall and L_wall_plasma. """ phi = np.linspace(-np.pi, np.pi, n_phi) X_PSF, PHI = np.meshgrid(x_psf, phi) rho = np.exp(a1*np.cos(PHI))/np.i0(a1) integrand = R_wall*rho*gaussian(R_wall*np.cos(PHI) - X_PSF, s_xy)*laplace(R_wall*np.sin(PHI), l) return np.trapz(integrand, x=phi, axis=0)
[docs] def F_lumen(x_psf, s_xy, l, R_lum, n_r=256): """ Part of the expression for L_plasma_no_glx. """ r = np.linspace(-R_lum, R_lum, n_r) X_PSF, R = np.meshgrid(x_psf, r) integrand = gaussian(R - X_PSF, s_xy)*(1 - np.exp(-np.sqrt(R_lum**2 - R**2)/l)) return np.trapz(integrand, x=r, axis=0)
[docs] def F_gcx(x_psf, s_xy, l, R_lum, R_wall, s_gcx, n_phi=256): """ Part of the expression for F_plasma. """ phi = np.linspace(0, np.pi, n_phi) X, PHI = np.meshgrid(x_psf, phi) a = np.sqrt(np.cos(PHI)**2/s_xy**2/2) b = (X*np.cos(PHI)/s_xy**2 - np.abs(np.sin(PHI))/l - 1/s_gcx)/2/a e1 = np.exp(-a**2*R_lum**2 + 2*b*a*R_lum - X**2/s_xy**2/2 + R_lum/s_gcx)*(1 + np.sqrt(np.pi)*b*erfcx(a*R_lum - b))/2/a**2 e2 = np.exp(-a**2*R_wall**2 + 2*b*a*R_wall - X**2/s_xy**2/2 + R_lum/s_gcx)*(1 + np.sqrt(np.pi)*b*erfcx(a*R_wall - b))/2/a**2 return np.trapz(e1 - e2, dx=phi[1]-phi[0], axis=0)/np.sqrt(2*np.pi*s_xy**2)/l
[docs] def F_plasma(x_psf, s_xy, l, R_lum, R_wall, s_gcx, n_phi=256, n_r=256): """ Part of the expression for L_plasma and L_wall_plasma. """ return F_lumen(x_psf, s_xy, l, R_lum, n_r=n_r) + F_gcx(x_psf, s_xy, l, R_lum, R_wall, s_gcx, n_phi=n_phi)
[docs] def L_plasma(x, xc, s_xy, l, R_lum, R_wall, s_gcx, I, b, n_phi=256, n_r=256): """ Full expression (with glycocalyx) for plasma line-scans of fluorescence. This function is fitted to line-profiles of plasma-fluorescence with MLE to track capillary walls (Protocol A). """ return (I - b)*F_plasma(x - xc, s_xy, l, R_lum, R_wall, s_gcx, n_phi=n_phi, n_r=n_r) + b
[docs] def L_plasma_no_glx(x, xc, s_xy, l, R_lum, I, b, n_r=256): """ Simplified (no glycocalyx) expression for plasma line-scans of fluorescence. This function is fitted to line-profiles of plasma-fluorescence with MLE to track capillary walls (Protocol B). """ return (I - b)*F_lumen(x - xc, s_xy, l, R_lum, n_r=n_r) + b
[docs] def L_wall(x, xc, s_xy, l, R_wall, a1, I, b_plasma, b_tissue, n_r=256, n_phi=256): """ Expression for plasma wall-scans of fluorescence. This function is fitted to line-profiles of wall-fluorescence with MLE to track capillary walls (Protocol C). """ return I*f_wall(x - xc, s_xy, l, R_wall, a1, n_phi=n_phi) + (b_plasma - b_tissue)*F_lumen(x - xc, s_xy, l, R_wall, n_r=n_r) + b_tissue
[docs] def L_wall_plasma(x, xc, s_xy, l, R_lum, R_wall, s_gcx, a1, Iw, Ip, b_plasma, b_tissue_wall, b_tissue_plasma, n_r=256, n_phi=256): """ Expressions for wall and plasma wall-scans of fluorescence. This function is fitted to line-profiles of wall- and plasma-fluorescence with MLE to track capillary walls (Protocol A). """ return np.array([L_wall(x, xc, s_xy, l, R_wall, a1, Iw, b_plasma, b_tissue_wall, n_r=n_r, n_phi=n_phi), L_plasma(x, xc, s_xy, l, R_lum, R_wall, s_gcx, Ip, b_tissue_plasma, n_r=n_r, n_phi=n_phi)])
#-------------------Ultimate Fit--------------------
[docs] def L_multi(x, s_xy, l, dR, s_gcx, b_plasma, b_tissue_wall, b_tissue_plasma, *pars, n_r=128, n_phi=128): """ Expressions for consecutive pairs (in time) of wall and plasma line-scans of fluorescence. Used in Protocol A for tracking capillary walls. """ Iw, Ip, R_wall, xc, a1 = np.reshape(np.asarray(pars), [5, len(pars)//5]) return np.array([[L_wall(x, xc_i, s_xy, l, R_wall_i, a1_i, Iw_i, b_plasma, b_tissue_wall, n_r=n_r, n_phi=n_phi), L_plasma(x, xc_i, s_xy, l, R_wall_i - dR, R_wall_i, s_gcx, Ip_i, b_tissue_plasma, n_r=n_r, n_phi=n_phi)] for Iw_i, Ip_i, R_wall_i, xc_i, a1_i in zip(Iw, Ip, R_wall, xc, a1)])
[docs] def L_multi_wall(x, s_xy, l, b_plasma, b_tissue_wall, *pars, n_r=128, n_phi=128): """ Expressions for consecutive (in time) wall-scans of fluorescence. Used in Protocol C for tracking capillary walls. """ Iw, R_wall, xc, a1 = np.reshape(np.asarray(pars), [4, len(pars)//4]) return np.array([L_wall(x, xc_i, s_xy, l, R_wall_i, a1_i, Iw_i, b_plasma, b_tissue_wall, n_r=n_r, n_phi=n_phi) for Iw_i, R_wall_i, xc_i, a1_i in zip(Iw, R_wall, xc, a1)])
[docs] def L_multi_plasma(x, s_xy, l, b_tissue_plasma, *pars, n_r=128): """ Expressions for consecutive (in time) plasma-scans of fluorescence. Used in Protocol B for tracking capillary walls. """ Ip, R_plasma, xc = np.reshape(np.asarray(pars), [3, len(pars)//3]) return np.array([L_plasma_no_glx(x, xc_i, s_xy, l, R_plasma_i, Ip_i, b_tissue_plasma, n_r=n_r) for Ip_i, R_plasma_i, xc_i in zip(Ip, R_plasma, xc)])