Latrunculin breaks motility without affecting chemoattractant-induced swelling

Source code notebook

using Bootstrap
using ColorSchemes
using CSV
using DataFrames
using Dates
using ImageFiltering
using Measures
using Measurements
using Plots
using Statistics
using StatsPlots
using Unitful

Load some basic utility code

rootfolder = normpath(joinpath(@__DIR__, "..", "..", "..", ".."))
include(joinpath(rootfolder, "figures", "utils.jl"))

Load CSV from disk and load the volume measurements with the associated error and add the XY resolution

types = Dict([:rel_volume, :abs_volume_um3] .=> Measurement{Float64})
linked = CSV.File(joinpath(rootfolder, "data", "fxm_uncaging_augmented.csv"), types = types) |> DataFrame
filter!(x->x.isencapsulated, linked);
# This value was computed manually for our 20x objective
linked.xunit = linked.x .* 0.653u"μm"
linked.yunit = linked.y .* 0.653u"μm";
linked.time = uconvert.(u"minute", linked.time_s .* u"s");
linked.reltime = linked.time .- 15u"minute"; # uncaging always happens at 15 minutes in

Compute the median volume and footprint area for each replicate at each time point

med_vols = combine(groupby(linked, [:reltime, :condition, :date, :dish]),
    :abs_volume_um3 => (x->median(Measurements.value.(x))) => :med_vol,
    :area_um2 => (x->median(Measurements.value.(x))) => :med_area,
    :abs_volume_um3 => length => :n);

Normalize the volumes to the average median volume in the 2 minutes prior to activation.

relative_med_vols = combine(groupby(med_vols, [:condition, :date, :dish]),
                            [:reltime, :med_vol] => ((t, v)->v ./ mean(v[-2u"minute" .< t .< 0u"minute"])) => :rel_med_vol,
                            :reltime, :n);

Compute the 95% confidence interval by bootstrapping the replicates

relative_med_vols_mean = combine(groupby(relative_med_vols, [:reltime, :condition]),
                            :rel_med_vol => (x->NamedTuple{(:v, :l, :u)}(confint(bootstrap(mean, x, BasicSampling(1_000)), BasicConfInt(0.95))[1])) => AsTable,
                            :n => (x->Ref(Array(x))) => :n_counts, :n => length, :reltime);

Throw out the data while the UV light is on since the UV LED wasn't switched off perfectly.

relative_med_vols_mean[0.0u"minute" .<= relative_med_vols_mean.reltime .< 0.5u"minute", [:v, :l, :u]] .= NaN;

Plot the volume response of Latrunculin vs WT cells

cmap = Dict("WT" => okabe_ito[1], "BIX" => okabe_ito[2], "Duvel" => okabe_ito[4], "BIXOSMO" => okabe_ito[8], "LatB" => okabe_ito[5])
vspan([2.5u"minute", 30u"minute"], alpha = 0.5, c = colorant"lightgray")
vspan!([0.5u"minute", 2.5u"minute"], label = "", alpha = 0.3, c = okabe_ito[8])
p = @df sort(filter(x->x.condition in ["WT", "LatB"] , relative_med_vols_mean), :reltime) plot!(:reltime,
    :v, group = :condition, ribbon = (:v .- :l, :u .- :v),
    ylabel = "Normalized cell volume", xlabel = P"Time (mins)",
    yticks = collect(0.90:0.1:1.20),
    framestyle = :axes, grid = :y, ylim = (0.95, 1.201),
    xticks = -10:10:30,
    xlim = (-10, 30), top_margin = 5mm, right_margin = 15mm,
    linewidth = 2, c = getindex.(Ref(cmap), :condition), leg = false, size = (480, 350))

annotate!(30.5, 1.14, text("Ctrl", "Helvetica Bold", okabe_ito[1], :left, 10))
annotate!(30.5, 1.095, text("LatB", "Helvetica Bold", okabe_ito[5], :left, 10))
vspan!([0, 0.5], label = "", alpha = 0.5, c = colorant"purple")
annotate!(-0.3, 1.165, text("fMLP\nuncage", RGBA(colorant"purple", 0.7), :right, 8))
annotate!(3.5, 1.18, text("migrating", "Helvetica Bold", colorant"gray", :left, 10))
annotate!(1.5, 1.22, text("spreading", "Helvetica Bold", RGBA(okabe_ito[8], 0.5), :center, 10))

savefig(p, joinpath("assets", "wt_vs_latb_volume.svg"))
p
−10 0 10 20 30 Time (mins) 1.0 1.1 1.2 Normalized cell volume Ctrl LatB migrating spreading

Plot the tracks of a representative WT condition

rectangle(w, h, x, y) = Shape(x .+ [0,w,w,0], y .+ [0,0,h,h])
function plottracks(df, cs)
    filter!(x->(256 .< x.x .< 768) .& (256 .< x.y .< 768), df)
    p1 = @df filter(x->x.reltime < 0u"minute", df) plot(:xunit, :yunit, group = :particle, line_z = :frame,
        leg = false, c = cgrad(cs), aspect_ratio = 1.0, xlim = (256, 768) .* 0.653, ylim = (256, 768) .* 0.653,
        linewidth = 2, xformatter = (_->""), yformatter = _ -> "", xlabel = "", ylabel = "",
        xgrid = false, ygrid = false, xticks = false, yticks = false, yflip = true,
        title = "Baseline")
    plot!(rectangle(50/0.653,15,550 + 10, 620 + 10),
          linewidth = 0, c=colorant"black", label = "")
    p2 = @df filter(x->x.reltime > 15u"minute", df) plot(:xunit, :yunit, group = :particle, line_z = :frame,
        leg = false, c = cgrad(cs), aspect_ratio = 1.0, xlim = (256, 768) .* 0.653, ylim = (256, 768) .* 0.653, left_margin = -10mm,
        linewidth = 2, xformatter = (_->""), yformatter = _ -> "", xlabel = "", ylabel = "",
        xgrid = false, ygrid = false, xticks = false, yticks = false, yflip = true,
        title = "Post-uncaging")
    plot!(rectangle(50/0.653,15,550 + 10, 620 + 10),
          linewidth = 0, c=colorant"black", label = "")
    plot(p1, p2, size = (800, 400))
end

tmp = filter(x -> x.condition == "WT" && x.date == Date(2023, 3, 6) && x.dish == "dish1", linked)

cs = ColorScheme([colorant"lightgray", okabe_ito[1]], "custom", "wt gradient")

plottracks(tmp, cs)
Baseline Post-uncaging

Plot the tracks of a representative LatB condition

tmp = filter(x -> x.condition == "LatB" && x.date == Date(2023, 9, 27) && x.dish == "dish2", linked)

cs = ColorScheme([colorant"lightgray", okabe_ito[5]], "custom", "wt gradient")

plottracks(tmp, cs)
Baseline Post-uncaging

Latrunculin vs WT footprint area response

relative_med_vols = combine(groupby(med_vols, [:condition, :date, :dish]),
                            [:reltime, :med_vol] => ((t, v)->v ./ mean(v[-2u"minute" .< t .< 0u"minute"])) => :rel_med_vol,
                            [:reltime, :med_area] => ((t, v)->v ./ mean(v[-2u"minute" .< t .< 0u"minute"])) => :rel_med_area,
                            :reltime, :n)

relative_med_vols_mean = combine(groupby(relative_med_vols, [:reltime, :condition]),
                            :rel_med_vol => std, :reltime,
                            :n => (x->Ref(Array(x))) => :n_counts, :n => length,
                            :rel_med_vol => (x->NamedTuple{(:v, :l, :u)}(confint(bootstrap(mean, x, BasicSampling(1_000)), BasicConfInt(0.95))[1])) => AsTable,
                            :rel_med_area => (x->NamedTuple{(:a, :a_l, :a_u)}(confint(bootstrap(mean, x, BasicSampling(1_000)), BasicConfInt(0.95))[1])) => AsTable)

relative_med_vols_mean[0.0u"minute" .<= relative_med_vols_mean.reltime .< 0.5u"minute", [:v, :l, :u]] .= NaN;

"""Compute the surface area for a given volume"""
surfarea(v) = π ^ (1/3) * (6v)^(2/3)

vspan([2.5u"minute", 30u"minute"], label = "", alpha = 0.5, c = colorant"lightgray")
vspan!([0.5u"minute", 2.5u"minute"], label = "", alpha = 0.3, c = okabe_ito[8])

c1 = colorant"gray50"
filter!(x->x.condition == "WT" || x.condition == "LatB", relative_med_vols_mean)
p = @df sort(relative_med_vols_mean, :reltime, rev = true) plot!(:reltime, :a,
    ribbon = (:a .- :a_l, :a_u .- :a),
    group = :condition,
    ylabel = "Mean rel. footprint size", xlabel = P"Time (mins)", xticks = collect(-10:10:30),
    yticks = collect(1:0.1:1.40),
    framestyle = :axes, grid = :y, ylim = (0.95, 1.452),
    rightmargin = 15mm,
    topmargin = 5mm,
    xlim = (-10, 30), label = "",
    linewidth = 2, c = getindex.(Ref(cmap), :condition),
    leg = :outerbottomright, size = (580, 350))
vspan!([0, 0.5], label = "", alpha = 0.5, c = colorant"purple")
annotate!(-0.3, 1.35, text("fMLP\nuncage", RGBA(colorant"purple", 0.7), :right, 8))
annotate!(30.5, 1.1, text("LatB", "Helvetica Bold", okabe_ito[5], :left, 10))
annotate!(30.5, 1.29, text("Ctrl", "Helvetica Bold", okabe_ito[1], :left, 10))

annotate!(3.5, 1.42, text("migration", "Helvetica Bold", colorant"gray", :left, 10))
annotate!(1.5, 1.48, text("spreading", "Helvetica Bold", RGBA(okabe_ito[8], 0.5), :center, 10))

@df filter(x->x.condition == "LatB", relative_med_vols_mean) plot!(ustrip.(:reltime),
    mapwindow(mean, surfarea.(:v) ./ surfarea(1.0), -3:3), c = colorant"salmon", linewidth = 2,
    label = "Spherical\nModel")
−10 0 10 20 30 Time (mins) 1.0 1.1 1.2 1.3 1.4 Mean rel. footprint size Spherical Model LatB Ctrl migration spreading

This page was generated using DemoCards.jl and Literate.jl.