ProCreations's picture
Publish validated GP-FVM reproduction
c711202 verified
Raw
History Blame Contribute Delete
6.73 kB
"""
Replot the calibration + scalability figures using a TuePlots theme,
reading saved outputs from `results/` rather than re-running the experiments.
Run from the repo root:
julia --project=. experiments/source_identification/replot_figures.jl
"""
using CairoMakie
using TuePlots
using CSV, DataFrames
using NPZ
const OUT_DIR = get(ENV, "GPFVM_FIGURES_DIR", joinpath(@__DIR__, "figures"))
const CALIB_DIR = joinpath(@__DIR__, "results", "calibration")
const SCAL_DIR = joinpath(@__DIR__, "results", "scalability")
# ──────────────────────────────────────────────────────────────────────────────
# Theme helpers
# ──────────────────────────────────────────────────────────────────────────────
function icml_theme(; single_column=true, nrows=1, ncols=1, ratio=0.75)
Theme(
TuePlots.SETTINGS[:ICML];
font=true, fontsize=true, figsize=true,
single_column=single_column,
nrows=nrows, ncols=ncols,
subplot_height_to_width_ratio=ratio,
)
end
# ──────────────────────────────────────────────────────────────────────────────
# Figure 1: calibration_plot.pdf (Appendix C)
# ──────────────────────────────────────────────────────────────────────────────
function replot_calibration()
df = CSV.read(joinpath(CALIB_DIR, "coverage.csv"), DataFrame)
nominal = df.nominal
emp_s = df.source_coverage
emp_c = df.conc_coverage
set_theme!(icml_theme(single_column=true, nrows=1, ncols=1, ratio=1.0))
fig = Figure()
ax = Axis(fig[1, 1];
xlabel="Nominal coverage",
ylabel="Empirical coverage",
aspect=1,
)
xlims!(ax, 0.45, 1.0); ylims!(ax, 0.45, 1.0)
lines!(ax, [0.45, 1.0], [0.45, 1.0]; color=:gray60, linestyle=:dash, linewidth=1, label="Perfect")
scatterlines!(ax, nominal, emp_s; color=:crimson, linewidth=1.6, markersize=6, label="Source")
scatterlines!(ax, nominal, emp_c; color=:royalblue, linewidth=1.6, markersize=6, label="Concentration")
axislegend(ax; position=:lt, framevisible=false)
out = joinpath(OUT_DIR, "calibration_plot.pdf")
save(out, fig, pt_per_unit=1)
set_theme!()
@info "Wrote $out"
end
# ──────────────────────────────────────────────────────────────────────────────
# Figure 2: spatial_coverage_95.pdf (Appendix C)
# ──────────────────────────────────────────────────────────────────────────────
function replot_spatial_coverage()
d = npzread(joinpath(CALIB_DIR, "calibration_data.npz"))
xs = d["xs"]
ys = d["ys"]
cov_s = d["spatial_s_cov_95"]
cov_c = d["spatial_c_cov_95"]
set_theme!(icml_theme(single_column=true, nrows=1, ncols=2, ratio=1.0))
fig = Figure()
ax1 = Axis(fig[1, 1]; aspect=DataAspect(), title="Source", xlabel=L"x", ylabel=L"y")
ax2 = Axis(fig[1, 2]; aspect=DataAspect(), title="Concentration", xlabel=L"x",
yticklabelsvisible=false, yticksvisible=false)
hm = heatmap!(ax1, xs, ys, cov_s; colormap=:RdBu, colorrange=(0.8, 1.0))
heatmap!(ax2, xs, ys, cov_c; colormap=:RdBu, colorrange=(0.8, 1.0))
Colorbar(fig[1, 3], hm; label="Empirical coverage at 95% nominal", width=8)
out = joinpath(OUT_DIR, "spatial_coverage_95.pdf")
save(out, fig, pt_per_unit=1)
set_theme!()
@info "Wrote $out"
end
# ──────────────────────────────────────────────────────────────────────────────
# Figure 3: scaling_timing_Ns.pdf (Appendix D)
# ──────────────────────────────────────────────────────────────────────────────
function replot_scaling_timing()
df = CSV.read(joinpath(SCAL_DIR, "scalability_results.csv"), DataFrame)
Ns = df.n_total
t_total = df.time_total_s
t_sparse = hasproperty(df, :time_sparse_prec_c_s) ? df.time_sparse_prec_c_s : nothing
t_cond = hasproperty(df, :time_conditioning_s) ? df.time_conditioning_s : nothing
t_post = hasproperty(df, :time_posterior_stats_s) ? df.time_posterior_stats_s : nothing
set_theme!(icml_theme(single_column=true, nrows=1, ncols=1, ratio=0.75))
fig = Figure()
ax = Axis(fig[1, 1];
xlabel=L"Total DOF $N_s$",
ylabel="Wall-clock time (s)",
xscale=log10, yscale=log10,
)
# Reference line O(N^{3/2})
Ns_ref = collect(range(extrema(Ns)...; length=20))
ref_anchor = t_total[1] / (Ns[1]^1.5)
lines!(ax, Ns_ref, ref_anchor .* Ns_ref .^ 1.5;
color=:gray60, linestyle=:dash, linewidth=1, label=L"\mathcal{O}(N_s^{3/2})")
scatterlines!(ax, Ns, t_total; color=:black, linewidth=1.6, markersize=6, label="Total")
t_sparse !== nothing && scatterlines!(ax, Ns, t_sparse; color=:royalblue, linewidth=1.4, markersize=5, label="Sparse prec.")
t_cond !== nothing && scatterlines!(ax, Ns, t_cond; color=:darkorange, linewidth=1.4, markersize=5, label="Conditioning")
t_post !== nothing && scatterlines!(ax, Ns, t_post; color=:purple, linewidth=1.4, markersize=5, label="Posterior stats")
axislegend(ax; position=:lt, framevisible=false)
out = joinpath(OUT_DIR, "scaling_timing_Ns.pdf")
save(out, fig, pt_per_unit=1)
set_theme!()
@info "Wrote $out"
end
# ──────────────────────────────────────────────────────────────────────────────
function main()
isdir(OUT_DIR) || mkpath(OUT_DIR)
replot_calibration()
replot_spatial_coverage()
replot_scaling_timing()
end
main()