-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
318 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
```@meta | ||
EditURL = "../../../../examples/Chemotaxis/celani_gauss2D.jl" | ||
``` | ||
|
||
# Noisy chemotaxis towards Gaussian source | ||
|
||
In this example we set up a static Gaussian source and observe the chemotactic behavior | ||
of the `Celani` model, in the presence of sensing noise (via the `chemotactic_precision`). | ||
Playing with the `chemotactic_precision`, it can be seen that the clustering of bacteria | ||
at the source becomes stronger with decreasing noise (decreasing chemotactic precision). | ||
|
||
````@example celani_gauss2D | ||
using MicrobeAgents | ||
using Plots | ||
function concentration_field(pos, model) | ||
C = model.C | ||
σ = model.σ | ||
p₀ = model.p₀ | ||
concentration_field(pos, p₀, C, σ) | ||
end | ||
concentration_field(pos, p₀, C, σ) = C * exp(-sum(abs2.(pos.-p₀))/(2*σ^2)) | ||
timestep = 0.1 # s | ||
extent = ntuple(_ -> 1000.0, 2) # μm | ||
space = ContinuousSpace(extent; periodic=false) | ||
p₀ = extent./2 # μm | ||
C = 1.0 # μM | ||
σ = 100.0 # μm | ||
properties = Dict( | ||
:concentration_field => concentration_field, | ||
:C => C, | ||
:σ => σ, | ||
:p₀ => p₀, | ||
) | ||
model = StandardABM(Celani{2}, space, timestep; properties) | ||
foreach(_ -> add_agent!(model; chemotactic_precision=6.0), 1:300) | ||
nsteps = 5000 | ||
adata = [position] | ||
adf, = run!(model, nsteps; adata) | ||
traj = vectorize_adf_measurement(adf, :position) | ||
xmesh = range(0, first(spacesize(model)); length=100) | ||
ymesh = range(0, last(spacesize(model)); length=100) | ||
c = [concentration_field(p, p₀, C, σ) for p in Iterators.product(xmesh, ymesh)] | ||
heatmap(xmesh, ymesh, c', cbar=false, ratio=1, c=:bone, axis=false) | ||
x = getindex.(traj,1)[end-100:4:end, :] | ||
y = getindex.(traj,2)[end-100:4:end, :] | ||
a = axes(x,1) ./ size(x,1) | ||
plot!(x, y, | ||
lab=false, lims=(0,1000), lw=1, alpha=a | ||
) | ||
```` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
```@meta | ||
EditURL = "../../../../examples/Chemotaxis/response_functions.jl" | ||
``` | ||
|
||
# Response function (Xie) | ||
|
||
In this example we will probe the response function implemented | ||
in the `Xie` model of chemotaxis. | ||
The impulse response function is the "output" of the bacterial chemotaxis | ||
pathway when presented with an input signal`. | ||
|
||
To do this, we will emulate another classical laboratory assay, where the | ||
bacterium is tethered to a wall, and it is exposed to a temporal change | ||
in the concentration of a chemoattractant. | ||
The response to the stimulus can be measured by observing modulations | ||
in the instantaneous tumbling rate. | ||
For each of the implemented microbe types, MicrobeAgents provides a | ||
`tumblebias` function which returns the instantaneous bias | ||
in the tumbling rate, evaluated from the internal state of the microbe. | ||
Monitoring the time evolution of the tumble bias under teporal stimuli | ||
then allows us to access the response function of the microbe. | ||
|
||
In the `Xie` model, chemotaxis is implemented by direct samplings of the | ||
`concentration_field`, thus we don't need to explicitly define neither | ||
a `concentration_gradient` nor a `concentration_time_derivative`. | ||
We will represent our temporal stimuli in the form of square waves which | ||
instantaneously switch from a baseline value `C₀` to a peak value `C₁+C₀` | ||
homogeneously over space. | ||
The excitation will occur at a time `t₁` and go back to baseline levels | ||
at a time `t₂`. | ||
|
||
````@example response_functions | ||
using MicrobeAgents | ||
using Plots | ||
θ(a,b) = a>b ? 1.0 : 0.0 # heaviside theta function | ||
function concentration_field(pos, model) | ||
C₀ = model.C₀ | ||
C₁ = model.C₁ | ||
t₁ = model.t₁ | ||
t₂ = model.t₂ | ||
dt = model.timestep | ||
t = abmtime(model) * dt | ||
# notice the time dependence! | ||
concentration_field(t, C₀, C₁, t₁, t₂) | ||
end | ||
concentration_field(t,C₀,C₁,t₁,t₂) = C₀+C₁*θ(t,t₁)*(1-θ(t,t₂)) | ||
space = ContinuousSpace(ntuple(_ -> 500.0, 3)) # μm | ||
C₀ = 0.01 # μM | ||
C₁ = 5.0-C₀ # μM | ||
T = 60.0 # s | ||
t₁ = 20.0 # s | ||
t₂ = 40.0 # s | ||
properties = Dict( | ||
:concentration_field => concentration_field, | ||
:C₀ => C₀, | ||
:C₁ => C₁, | ||
:t₁ => t₁, | ||
:t₂ => t₂, | ||
) | ||
dt = 0.1 # s | ||
model = StandardABM(Xie{3}, space, dt; properties) | ||
```` | ||
|
||
A peculiarity of the `Xie` model is that the chemotactic properties of the | ||
microbe differ between the forward and backward motile states, so we can | ||
probe the response function in both the forward and backward motile state | ||
by initializing two distinct microbes in the two states. | ||
To keep the microbes in these motile states for the entire experiment duration, | ||
we suppress their tumbles, and (just for total consistency with experiments) | ||
we also set their speed to 0. | ||
|
||
````@example response_functions | ||
add_agent!(model; turn_rate_forward=0, | ||
motility=RunReverseFlick(motile_state=MotileState(Forward), speed=[0]) | ||
) | ||
add_agent!(model; turn_rate_backward=0, | ||
motility=RunReverseFlick(motile_state=MotileState(Backward), speed=[0]) | ||
) | ||
```` | ||
|
||
In addition to the `tumblebias`, we will also monitor two other quantities | ||
`state_m` and `state_z` which are internal variables of the `Xie` model | ||
which represent the methylation and dephosphorylation processes which | ||
together control the chemotactic response of the bacterium. | ||
|
||
````@example response_functions | ||
nsteps = round(Int, T/dt) | ||
#state(a::Xie) = max(tumblebias(a)*a.state, 0) | ||
adata = [tumblebias, :state_m, :state_z] | ||
adf, = run!(model, nsteps; adata) | ||
S = vectorize_adf_measurement(adf, :tumblebias) | ||
m = (vectorize_adf_measurement(adf, :state_m))[:,1] # take only fw | ||
z = (vectorize_adf_measurement(adf, :state_z))[:,1] # take only fw | ||
```` | ||
|
||
We first look at the response function in the forward and backward | ||
motile state: when the concentration increases we have a sharp negative | ||
response (the tumble bias decreases), then the bacterium adapts to the new | ||
concentration level, and when it drops back to the basal level we observe | ||
a sharp positive response (the tumble bisa increases) before adapting | ||
again to the new concentration level. | ||
|
||
````@example response_functions | ||
_green = palette(:default)[3] | ||
plot() | ||
x = (0:dt:T) .- t₁ | ||
plot!( | ||
x, S, | ||
lw=1.5, lab=["Forward" "Backward"] | ||
) | ||
plot!(ylims=(-0.1,4.5), ylab="Response", xlab="time (s)") | ||
plot!(twinx(), | ||
x, t -> concentration_field(t.+t₁,C₀,C₁,t₁,t₂), | ||
ls=:dash, lw=1.5, lc=_green, lab=false, | ||
tickfontcolor=_green, | ||
ylab="C (μM)", guidefontcolor=_green | ||
) | ||
```` | ||
|
||
By analysing the methylation and dephosphorylation processes, we can | ||
understand how the chemotactic response arises. | ||
First, when the concentration increases, both `m` and `z` increase and converge | ||
to a new steady-state value, but since they respond on different timescales, | ||
the response (defined by the difference between these two quantities), shows | ||
a sharp decrease followed by a slower relaxation. | ||
The same occurs for the negative stimulus. | ||
|
||
````@example response_functions | ||
x = (0:dt:T) .- t₁ | ||
τ_m = model[1].adaptation_time_m | ||
τ_z = model[1].adaptation_time_z | ||
M = m ./ τ_m | ||
Z = z ./ τ_z | ||
R = M .- Z | ||
plot( | ||
x, [M Z R], | ||
lw=2, | ||
lab=["m/τ_m" "z/τ_z" "m/τ_m - z/τ_z"], | ||
xlab="time (s)" | ||
) | ||
```` | ||
|
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.