| """ |
| 2D visualization replicating Figure 2 from Chen, Owhadi, Schäfer (2024). |
| |
| Compares screening effects between different measurement orderings: |
| - Left: Many Diracs + one integral test → shows if integral is screened by Diracs |
| - Right: Many integrals + one Dirac test → shows if Dirac is screened by integrals |
| |
| Each case uses a simple 2x2 block matrix [bulk, test; test, test]. |
| """ |
|
|
| using FunctionalGPs, GaussianMarkovRandomFields |
| using LinearAlgebra |
| using CairoMakie |
| using GPFiniteVolume |
|
|
| """ |
| create_2d_screening_figure(; N_xy=20, kernel_lengthscale=0.1, test_point=[0.5, 0.5]) |
| |
| Create 2D screening visualization comparing Dirac vs integral orderings. |
| """ |
| function create_2d_screening_figure(; |
| N_xy = 41, |
| kernel_lengthscale = 0.1, |
| kernel_smoothness = 1, |
| test_point = [0.5, 0.5], |
| output_dir = "figures" |
| ) |
|
|
| println("Setting up 2D screening comparison (Figure 2 style)...") |
| println("Grid size: $(N_xy)x$(N_xy) = $(N_xy^2) points") |
|
|
| |
| k_base = HalfIntegerMaternKernel(kernel_smoothness, kernel_lengthscale) |
| k_prod = k_base ⊗ k_base |
|
|
| |
| N_total = N_xy^2 |
| Xs_base = range(0.0, 1.0, length=N_xy) |
| Xs = FactorizedGrid(Xs_base, Xs_base) |
|
|
| |
| Xs_flat = reshape(collect(Iterators.product(Xs_base, Xs_base)), 1, N_total) |
| X = zeros(2, N_total) |
| for i in 1:N_total |
| X[:, i] .= Xs_flat[i] |
| end |
|
|
| |
| dists = [norm(X[:, i] - test_point) for i in 1:N_total] |
| test_idx = argmin(dists) |
| test_loc = X[:, test_idx] |
| println("Test point: $(test_loc)") |
|
|
| |
| |
| |
| println("\n=== Case A: Many Diracs + One Integral test ===") |
|
|
| |
| L_eval_bulk = EvaluationFunctional(Xs) |
|
|
| |
| |
| base_intervals = intervals_from_endpoints(collect(Xs_base)) |
| test_cell_x_idx = findfirst(i -> test_loc[1] in base_intervals[i], 1:length(base_intervals)) |
| test_cell_y_idx = findfirst(i -> test_loc[2] in base_intervals[i], 1:length(base_intervals)) |
|
|
| |
| test_domain_x = [base_intervals[test_cell_x_idx]] |
| test_domain_y = [base_intervals[test_cell_y_idx]] |
| test_domains = test_domain_x ⊗ test_domain_y |
| L_integ_test = VectorizedLebesgueIntegral(test_domains) |
|
|
| |
| L_stack_A = StackedLinearFunctional(L_integ_test, L_eval_bulk) |
| K_A = Matrix(L_stack_A(L_stack_A(k_prod))) |
|
|
| println("K_A size: $(size(K_A))") |
|
|
| |
| K_A_inv = inv(Symmetric(K_A + 1e-10*I)) |
| L_A = cholesky(Symmetric(K_A_inv)).L |
|
|
| |
| col_A = L_A[:, 1] |
|
|
| |
| coords_A = X |
|
|
| |
| |
| |
| println("\n=== Case B: Many Integrals + One Dirac test ===") |
|
|
| |
| domains_bulk = base_intervals ⊗ base_intervals |
| L_integ_bulk = VectorizedLebesgueIntegral(domains_bulk) |
|
|
| |
| test_grid = FactorizedGrid([test_loc[1]], [test_loc[2]]) |
| L_eval_test = EvaluationFunctional(test_grid) |
|
|
| |
| L_stack_B = StackedLinearFunctional(L_eval_test, L_integ_bulk) |
| K_B = Matrix(L_stack_B(L_stack_B(k_prod))) |
|
|
| println("K_B size: $(size(K_B))") |
|
|
| |
| K_B_inv = inv(Symmetric(K_B + 1e-10*I)) |
| L_B = cholesky(Symmetric(K_B_inv)).L |
|
|
| |
| col_B = L_B[:, 1] |
|
|
| |
| |
| n_cells = length(base_intervals)^2 |
| coords_B = zeros(2, n_cells) |
| idx = 1 |
| for iy in 1:length(base_intervals) |
| for ix in 1:length(base_intervals) |
| coords_B[1, idx] = midpoint(base_intervals[ix]) |
| coords_B[2, idx] = midpoint(base_intervals[iy]) |
| idx += 1 |
| end |
| end |
|
|
| |
| |
| |
| println("\nCreating figure...") |
| fig = Figure(size=(1400, 600), fontsize=14) |
|
|
| |
| col_A_bulk = col_A[2:end] |
| col_B_bulk = col_B[2:end] |
|
|
| |
| col_A_normalized = col_A_bulk ./ maximum(abs.(col_A_bulk)) |
| col_B_normalized = col_B_bulk ./ maximum(abs.(col_B_bulk)) |
|
|
| |
| log_vals_A = log10.(abs.(col_A_normalized) .+ 1e-16) |
| log_vals_B = log10.(abs.(col_B_normalized) .+ 1e-16) |
|
|
| println("Normalized range A: [$(round(minimum(log_vals_A), digits=2)), 0.0]") |
| println("Normalized range B: [$(round(minimum(log_vals_B), digits=2)), 0.0]") |
|
|
| |
| vmin = min(minimum(log_vals_A), minimum(log_vals_B)) |
| vmin = -12.0 |
| vmax = 0.0 |
|
|
| |
| ax1 = Axis(fig[1, 1], |
| xlabel = "x", |
| ylabel = "y", |
| title = "Function evaluations first", |
| aspect = DataAspect() |
| ) |
|
|
| sc1 = scatter!(ax1, coords_A[1, :], coords_A[2, :], |
| color = log_vals_A, |
| colormap = :turbo, |
| colorrange = (vmin, vmax), |
| markersize = 10 |
| ) |
|
|
| |
| scatter!(ax1, [test_loc[1]], [test_loc[2]], |
| color = :tomato, marker = :rect, markersize = 30, |
| strokecolor = :tomato, strokewidth = 2, label = "Test integral", alpha=0.9) |
|
|
| |
| ax2 = Axis(fig[1, 2], |
| xlabel = "x", |
| ylabel = "y", |
| title = "Integrals first", |
| aspect = DataAspect() |
| ) |
|
|
| sc2 = scatter!(ax2, coords_B[1, :], coords_B[2, :], |
| color = log_vals_B, |
| colormap = :turbo, |
| colorrange = (vmin, vmax), |
| markersize = 10, marker=:rect |
| ) |
|
|
| |
| scatter!(ax2, [test_loc[1]], [test_loc[2]], |
| color = :tomato, markersize = 30, |
| strokecolor = :tomato, strokewidth = 2, label = "Test Dirac", alpha=0.9) |
|
|
| |
| Colorbar(fig[1, 3], sc1, label = "log₁₀(|Lᵢⱼ|/max|Lᵢⱼ|)") |
|
|
| |
| mkpath(output_dir) |
| save(joinpath(output_dir, "screening_comparison_2d.pdf"), fig) |
| save(joinpath(output_dir, "screening_comparison_2d.png"), fig, px_per_unit=3) |
| println("\nSaved: screening_comparison_2d.pdf/png") |
|
|
| return fig |
| end |
|
|
| |
| if abspath(PROGRAM_FILE) == @__FILE__ |
| create_2d_screening_figure() |
| end |
|
|