# Find project root and include ensure_packages.jl
project_root = let
current = pwd()
while !isfile(joinpath(current, "Project.toml")) && !isfile(joinpath(current, "_quarto.yml"))
parent = dirname(current)
parent == current && break
current = parent
end
current
end
include(joinpath(project_root, "scripts", "ensure_packages.jl"))
@auto_using DifferentialEquations Random CairoMakie
# Check if GlobalSensitivity is available
global_sensitivity_available = false
try
using GlobalSensitivity
global_sensitivity_available = true
catch
println("Note: GlobalSensitivity.jl not available. This example requires GlobalSensitivity.jl.")
end
if global_sensitivity_available
# SIR model
function sir!(du, u, p, t)
S, I, R = u
β, γ = p
du[1] = -β * S * I
du[2] = β * S * I - γ * I
du[3] = γ * I
end
# Model function for sensitivity analysis
function model_function(p)
β, γ = p
u0 = [0.99, 0.01, 0.0]
tspan = (0.0, 50.0)
prob = ODEProblem(sir!, u0, tspan, (β, γ))
sol = solve(prob, Tsit5())
if sol.retcode != :Success
return 0.0
end
# Output: peak infection rate
return maximum([u[2] for u in sol.u])
end
# Parameter bounds: β ∈ [0.1, 0.5], γ ∈ [0.05, 0.2]
bounds = [(0.1, 0.5), (0.05, 0.2)]
# Sobol sensitivity analysis
Random.seed!(42)
sobol_result = gsa(model_function, Sobol(), bounds, samples = 1000)
# Visualise results
let
fig = Figure(size = (1000, 400))
ax1 = Axis(fig[1, 1], title = "First-Order Sobol Indices",
xlabel = "Parameter", ylabel = "Sensitivity Index",
xticks = ([1, 2], ["β (transmission)", "γ (recovery)"]))
ax2 = Axis(fig[1, 2], title = "Total-Order Sobol Indices",
xlabel = "Parameter", ylabel = "Sensitivity Index",
xticks = ([1, 2], ["β (transmission)", "γ (recovery)"]))
barplot!(ax1, [1, 2], sobol_result.S1, color = [:blue, :red])
barplot!(ax2, [1, 2], sobol_result.ST, color = [:blue, :red])
# Add value labels
for (i, val) in enumerate(sobol_result.S1)
text!(ax1, i, val + 0.02, text = string(round(val, digits=3)),
align = (:center, :bottom), fontsize = 12)
end
for (i, val) in enumerate(sobol_result.ST)
text!(ax2, i, val + 0.02, text = string(round(val, digits=3)),
align = (:center, :bottom), fontsize = 12)
end
fig
end
println("Global sensitivity analysis (Sobol indices):")
println(" First-order indices (main effects):")
println(" S_β = ", round(sobol_result.S1[1], digits=3))
println(" S_γ = ", round(sobol_result.S1[2], digits=3))
println(" Total-order indices (including interactions):")
println(" ST_β = ", round(sobol_result.ST[1], digits=3))
println(" ST_γ = ", round(sobol_result.ST[2], digits=3))
println("\nInterpretation:")
println(" β has ", sobol_result.S1[1] > sobol_result.S1[2] ? "larger" : "smaller",
" main effect on peak infection")
if sobol_result.ST[1] > sobol_result.S1[1] || sobol_result.ST[2] > sobol_result.S1[2]
println(" Parameter interactions are present (ST > S1)")
end
else
println("Skipping global sensitivity analysis: GlobalSensitivity.jl not available")
end