Velocity autocorrelation functions

Orientational correlations in the microbe's motion can be probed through velocity autocorrelation functions. Each motility pattern is characterized by a specific form of the velocity autocorrelation function, which have been analytically evaluated by Taktikos et al (PLoS ONE 2012). We will compare the velocity autocorrelation functions of run-tumble, run-reverse and run-reverse-flick motility, in the absence of rotational diffusion, to the analytical calculations:

\[\phi(t) = \begin{cases} \exp(-t/\tau), & \text{run-tumble} \\ \exp(-2t/\tau), & \text{run-reverse} \\ (1 - t/2\tau)\exp(-t/\tau), & \text{run-reverse-flick} \end{cases}\]

using MicrobeAgents
using Plots

U = 30.0 # μm/s
τ_run = 1.0 # s
turn_rate = 1 / τ_run # 1/s
Δt = 0.01 # s
L = 1e4 # μm
space = ContinuousSpace((L,L,L))

model = StandardABM(Microbe{3}, space, Δt; container=Vector)
n = 200
for Mot in (RunTumble, RunReverse, RunReverseFlick), i in 1:n
    if Mot == RunTumble
        motility = RunTumble([U], τ_run, Isotropic(3))
    else
        motility = Mot([U], τ_run, [U], τ_run)
    end
    add_agent!(model; motility)
end
# keep track of ids of each motile strategy
ids_runtumble = 1:n
ids_runreverse = (1:n) .+ n
ids_runrevflick = (1:n) .+ 2n

nsteps = round(Int, 100τ_run / Δt)
adata = [direction]
adf, = run!(model, nsteps; adata)

# separate the dataframes by motile strategy
adf_runtumble = filter(:id => id -> id in ids_runtumble, adf; view=true)
adf_runrev = filter(:id => id -> id in ids_runreverse, adf; view=true)
adf_runrevflick = filter(:id => id -> id in ids_runrevflick, adf; view=true)
adfs = [adf_runtumble, adf_runrev, adf_runrevflick]

# evaluate the autocorrelation functions
using StatsBase: mean
t = range(0, (nsteps-1)*Δt; step=Δt)
Φ = hcat([mean(Analysis.acf(a, :direction; normalize=true)) for a in adfs]...)

# from Taktikos et al.
Φ_theoretical = hcat([
    exp.(-t ./ τ_run),
    exp.(-t ./ (τ_run / 2)),
    (1 .- t ./ (2τ_run)) .* exp.(-t ./ τ_run),
]...)

plot(
    xlims=(0,6τ_run), ylims=(-0.1, 1.05),
    xlab="Δt / τ",
    ylab="velocity autocorrelation",
)
plot!(t, Φ_theoretical, lw=2, lc=[1 2 3],
    label=["Run-Tumble" "Run-Reverse" "Run-Reverse-Flick"]
)
# show simulation values only at selected lags for better visualization
lags = range(0, length(t)-1; step=20)
scatter!(t[lags.+1], Φ[lags.+1,:], m=:x, mc=[1 2 3], msw=2, label=false)
hline!([0.0], lw=0.8, ls=:dash, lc=:black, lab=false)
Example block output