From f1f7e38889fd98c6a4f3b5938230d2334d38163b Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro de Almeida Date: Fri, 13 Sep 2024 20:04:14 +1000 Subject: [PATCH] Add diff_map to plot difference to counterfactual map --- ext/AvizExt/viz/spatial.jl | 40 ++++++++++++++++++++++++++++---------- ext/AvizExt/viz/viz.jl | 7 +++++++ src/metrics/spatial.jl | 21 ++++++++++++++++++++ src/viz/viz.jl | 1 + test/analysis.jl | 3 ++- test/runtests.jl | 1 + test/viz/spatial.jl | 22 +++++++++++++++++++++ 7 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 test/viz/spatial.jl diff --git a/ext/AvizExt/viz/spatial.jl b/ext/AvizExt/viz/spatial.jl index 6722e3e9a..10d988dd3 100644 --- a/ext/AvizExt/viz/spatial.jl +++ b/ext/AvizExt/viz/spatial.jl @@ -48,6 +48,7 @@ end highlight::Union{Vector,Tuple,Nothing}, show_colorbar::Bool=true, colorbar_label::String="", + color_map::$COLORMAP_TYPE_DOCSTRING, legend_params::Union{Tuple,Nothing}=nothing, axis_opts::Dict{Symbol, <:Any}=set_axis_defaults(Dict{Symbol,Any}()) ) @@ -71,13 +72,13 @@ function create_map!( f::Union{GridLayout,GridPosition}, geodata::Vector{<:GeoMakie.GeometryBasics.MultiPolygon}, data::Observable, - highlight::Union{Vector,Tuple,Nothing}, + highlight::Union{Vector,Tuple,Nothing}; show_colorbar::Bool=true, colorbar_label::String="", - color_map::Union{Symbol,Vector{Symbol},RGBA{Float32},Vector{RGBA{Float32}}}=:grayC, + color_map::COLORMAP_TYPE(T)=:grayC, legend_params::Union{Tuple,Nothing}=nothing, axis_opts::OPT_TYPE=set_axis_defaults(DEFAULT_OPT_TYPE()) -) +)::Union{GridLayout,GridPosition} where {T<:Real} spatial = GeoAxis( f[1, 1]; axis_opts... @@ -86,10 +87,11 @@ function create_map!( # spatial.xticklabelsize = 14 # spatial.yticklabelsize = 14 + min_val = @lift(minimum($data)) max_val = @lift(maximum($data)) # Plot geodata polygons using data as internal color - color_range = (0.0, max_val[]) + color_range = min_val[] < 0 ? (min_val[], max_val[]) : (0, max_val[]) poly!( spatial, @@ -240,12 +242,30 @@ function ADRIA.viz.map!( g, geodata, data, - highlight, - show_colorbar, - c_label, - color_map, - legend_params, - axis_opts + highlight; + show_colorbar=show_colorbar, + colorbar_label=c_label, + color_map=color_map, + legend_params=legend_params, + axis_opts=axis_opts + ) +end + +function ADRIA.viz.diff_map( + rs::ResultSet, + diff_outcome::YAXArray{T}; + opts::Dict{Symbol,<:Any}=Dict{Symbol,Any}(), + fig_opts::Dict{Symbol,<:Any}=Dict{Symbol,Any}(), + axis_opts::Dict{Symbol,<:Any}=Dict{Symbol,Any}() +) where {T} + # TODO hande the cases where thes only positive or only negative values + min_val, max_res = extrema(diff_outcome) + mid_val = -min_val / (max_res - min_val) + + div_cmap::Vector{RGB{Float64}} = diverging_palette(10, 200; mid=mid_val) + opts[:color_map] = div_cmap + return ADRIA.viz.map( + rs, diff_outcome; axis_opts=axis_opts, opts=opts, fig_opts=fig_opts ) end diff --git a/ext/AvizExt/viz/viz.jl b/ext/AvizExt/viz/viz.jl index 140539677..28f954d2a 100644 --- a/ext/AvizExt/viz/viz.jl +++ b/ext/AvizExt/viz/viz.jl @@ -13,6 +13,13 @@ using .AvizExt const OPT_TYPE = Dict{Symbol,<:Any} const DEFAULT_OPT_TYPE = Dict{Symbol,Any} +const COLORMAP_TYPE_DOCSTRING = replace(""" +Union{ +Symbol,RGB{T},RGBA{T},Vector{Symbol},Vector{RGBA{T}},Vector{RGB{T}} +} +""", "\n" => "") +const COLORMAP_TYPE = eval(Meta.parse("f(T)=$COLORMAP_TYPE_DOCSTRING")) + """ _time_labels(labels) diff --git a/src/metrics/spatial.jl b/src/metrics/spatial.jl index 0bc1f325c..3057ee0b1 100644 --- a/src/metrics/spatial.jl +++ b/src/metrics/spatial.jl @@ -134,6 +134,27 @@ each location. - `outcome` : Metric outcome with dimensions (:timesteps, :locations, :scenarios) - `scens` : Scenarios DataFrame +# Examples +``` +# Load domain +dom = ADRIA.load_domain(path_to_domain) + +# Create scenarios +num_scens = 2^6 +scens = ADRIA.sample(dom, num_scens) + +# Run model +rs = ADRIA.run_scenarios(dom, scens, "45") + +# Calculate difference to the counterfactual for given metric +_relative_cover = metrics.relative_cover(rs) +gd_results, ug_results = metrics.cf_difference_loc(_relative_cover, scens) + +# Plot maps of difference to the counterfactual +ADRIA.viz.diff_map(rs, gd_results[2, :]) +ADRIA.viz.diff_map(rs, ug_results[2, :]) +``` + # Returns Two elements tuple with mean bootstrapped difference (counterfactual - guided) and (counterfactual - unguided) for each location. diff --git a/src/viz/viz.jl b/src/viz/viz.jl index 96a2b657e..ec29ac86c 100644 --- a/src/viz/viz.jl +++ b/src/viz/viz.jl @@ -42,6 +42,7 @@ function ranks_to_frequencies!() end # Spatial function map() end function map!() end +function diff_map() end function connectivity() end function connectivity!() end diff --git a/test/analysis.jl b/test/analysis.jl index 8e1f38e98..e8d7aae5e 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -7,9 +7,10 @@ if !@isdefined(TEST_RS) const TEST_DOM, TEST_N_SAMPLES, TEST_SCENS, TEST_RS = test_rs() end +Makie.inline!(false) + """Test larger scenario run with figure creation""" function test_rs_w_fig(rs::ADRIA.ResultSet, scens::ADRIA.DataFrame) - Makie.inline!(false) # Visualize results (in terms of absolute coral cover) s_tac = ADRIA.metrics.scenario_total_cover(rs) diff --git a/test/runtests.jl b/test/runtests.jl index f9fa825fc..3f755ec24 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -25,6 +25,7 @@ include("metrics/metrics.jl") include("metrics/spatial.jl") include("utils/scale.jl") include("utils/text_display.jl") +include("viz/spatial.jl") # TODO Fix spatial_clustering and site_selection tests # include("site_selection.jl") diff --git a/test/viz/spatial.jl b/test/viz/spatial.jl new file mode 100644 index 000000000..07f440a0b --- /dev/null +++ b/test/viz/spatial.jl @@ -0,0 +1,22 @@ +using WGLMakie, GeoMakie, GraphMakie +using ADRIA: viz +using ADRIA: YAXArray +using ADRIA: metrics, metrics.cf_difference_loc + +if !@isdefined(TEST_RS) + const TEST_DOM, TEST_N_SAMPLES, TEST_SCENS, TEST_RS = test_rs() +end + +Makie.inline!(false) +@testset "spatial" begin + fig_opts = Dict(:size => (1600, 800)) + + @testset "diff_map" begin + gd_diff::YAXArray{<:Real,2}, ug_diff::YAXArray{<:Real,2} = cf_difference_loc( + metrics.relative_cover(TEST_RS), TEST_SCENS + ) + + viz.diff_map(TEST_RS, gd_diff[2, :]; fig_opts=fig_opts) + viz.diff_map(TEST_RS, ug_diff[2, :]; fig_opts=fig_opts) + end +end