From 768c2f144ad921405b576cedab4bd7536f03725c Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Tue, 16 Jul 2024 16:41:57 +0100 Subject: [PATCH 01/14] initial commit for plotting recipies --- Project.toml | 6 +- src/plotting/plot_recipes.jl | 178 +++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 src/plotting/plot_recipes.jl diff --git a/Project.toml b/Project.toml index df2b7d2cf..a051fc93f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,6 @@ name = "UncertaintyQuantification" uuid = "7183a548-a887-11e9-15ce-a56ab60bad7a" -authors = [ - "Jasper Behrensdorf ", - "Ander Gray ", -] +authors = ["Jasper Behrensdorf ", "Ander Gray "] version = "0.9.0" [deps] @@ -25,6 +22,7 @@ Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70" Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl new file mode 100644 index 000000000..1f3f148e4 --- /dev/null +++ b/src/plotting/plot_recipes.jl @@ -0,0 +1,178 @@ +using RecipesBase + +DEFAULT_ALPHA = 0.2 +DEFAULT_LABEL = "" +DEFAULT_GRID = false +DEFAULT_LEGEND = false +DEFAULT_DISTRIBUTION = :pdf +DEFAULT_FILL = :gray +DEFAULT_COLOUR_PDF = :blue +DEFAULT_COLOUR_UPPER = :red +DEFAULT_COLOUR_LOWER = :black + +DEFAULT_PLOT_RANGE_EXTEND = 0.2 +DEFAULT_PLOT_RANGE_INTERVAL = 0.4 +DEFAULT_PLOT_GRID_NUMBER = 500 +DEFAULT_FONT_SIZE = 18 +DEFAULT_TICK_SIZE = 12 + + +@recipe function _plot(x::RandomVariable) + + grid --> DEFAULT_GRID + legend --> DEFAULT_LEGEND + ylabel --> "pdf" + xlabel --> x.name + + lo_grid = quantile(x, 0.001) + hi_grid = quantile(x, 0.999) + + lo_grid = x.lb + hi_grid = x.ub + + width = (hi_grid + lo_grid)/2 + + lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) + hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) + + x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) + pdf_evals = pdf.(Ref(x), x_grid) + + @series begin + fillrange := pdf_evals + color := DEFAULT_FILL + fillalpha := DEFAULT_ALPHA + x_grid, zeros(length(x_grid)) + end + + @series begin + color --> DEFAULT_COLOUR_PDF + alpha := 1 + label := "" + x_grid, pdf_evals + end +end + +@recipe function _plot(x::Interval) + + grid --> DEFAULT_GRID + legend --> DEFAULT_LEGEND + ylabel --> "cdf" + xlabel --> x.name + + lo_grid = x.lb + hi_grid = x.ub + + width = (hi_grid + lo_grid)/2 + + lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_INTERVAL) + hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_INTERVAL) + + x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) + + cdf_lo = x_grid .>= x.ub + cdf_hi = x_grid .>= x.lb + + @series begin + fillrange := cdf_hi + color := DEFAULT_FILL + fillalpha := DEFAULT_ALPHA + x_grid, cdf_lo + end + + @series begin + color --> DEFAULT_COLOUR_LOWER + alpha := 1 + label := "" + x_grid, cdf_lo + end + + @series begin + color --> DEFAULT_COLOUR_UPPER + alpha := 1 + label := "" + x_grid, cdf_hi + end + +end + +@recipe function _plot(x::ProbabilityBox) + + grid --> DEFAULT_GRID + legend --> DEFAULT_LEGEND + ylabel --> "cdf" + xlabel --> x.name + + lo_grid = quantile(x, 0.001)[1] + hi_grid = quantile(x, 0.999)[2] + + width = (hi_grid + lo_grid)/2 + + lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) + hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) + + x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) + cdf_evals = cdf.(Ref(x), x_grid) + + @series begin + fillrange := hi.(cdf_evals) + color := DEFAULT_FILL + fillalpha := DEFAULT_ALPHA + x_grid, lo.(cdf_evals) + end + + @series begin + color --> DEFAULT_COLOUR_LOWER + alpha := 1 + label := "" + x_grid, lo.(cdf_evals) + end + + @series begin + color --> DEFAULT_COLOUR_UPPER + alpha := 1 + label := "" + x_grid, hi.(cdf_evals) + end +end + + +### +# This code is a modified version of the plot recipe from IntervalArithmetic.jl +# https://github.com/JuliaIntervals/IntervalArithmetic.jl +### + +# Plot a 2D IntervalBox: +@recipe function _plot(x::Interval, y::Interval) #; customcolor = :green, alpha=0.5) + + seriesalpha --> DEFAULT_ALPHA + seriestype := :shape + + x = [x.lb, x.ub, x.ub, x.lb] + y = [y.lb, y.lb, y.ub, y.ub] + + x, y +end + +# Plot a vector of 2D IntervalBoxes: +@recipe function _plot(xx::Vector{T}, yy::Vector{T}) where T<:Interval + + seriestype := :shape + + xs = Float64[] + ys = Float64[] + + # build up coords: # (alternative: use @series) + for i = 1:length(xx) + (x, y) = (xx[i], yy[i]) + + # use NaNs to separate + append!(xs, [x.lb, x.ub, x.ub, x.lb, NaN]) + append!(ys, [y.lb, y.lb, y.ub, y.ub, NaN]) + + end + + seriesalpha --> DEFAULT_ALPHA + xs, ys + +end From bdea02ad27d3bf1593b1aa6b96bb4f459c51c4db Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Fri, 19 Jul 2024 17:21:21 +0100 Subject: [PATCH 02/14] working plotting with UQInputs vector --- Project.toml | 6 ++--- src/UncertaintyQuantification.jl | 4 ++++ src/inputs/imprecise/interval.jl | 5 ++++ src/plotting/plot_recipes.jl | 40 +++++++++++++++++++++----------- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Project.toml b/Project.toml index d4d4ab5a8..0ed15b71c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,6 @@ name = "UncertaintyQuantification" uuid = "7183a548-a887-11e9-15ce-a56ab60bad7a" -authors = [ - "Jasper Behrensdorf ", - "Ander Gray ", -] +authors = ["Jasper Behrensdorf ", "Ander Gray "] version = "0.10.0" [deps] @@ -23,6 +20,7 @@ KernelDensity = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MeshAdaptiveDirectSearch = "f4d74008-4565-11e9-04bd-4fe404e6a92a" Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" diff --git a/src/UncertaintyQuantification.jl b/src/UncertaintyQuantification.jl index 264880faa..f0db4a0ba 100644 --- a/src/UncertaintyQuantification.jl +++ b/src/UncertaintyQuantification.jl @@ -19,6 +19,8 @@ using QuasiMonteCarlo using Random using Reexport using StatsBase +using Plots +using RecipesBase @reexport using Distributions @@ -186,6 +188,8 @@ include("reliability/probabilityoffailure.jl") include("reliability/probabilityoffailure_imprecise.jl") include("sensitivity/sobolindices.jl") +include("plotting/plot_recipes.jl") + include("util/wrap.jl") include("util/imprecise.jl") diff --git a/src/inputs/imprecise/interval.jl b/src/inputs/imprecise/interval.jl index c60b2385f..08e2ade2d 100644 --- a/src/inputs/imprecise/interval.jl +++ b/src/inputs/imprecise/interval.jl @@ -42,3 +42,8 @@ function bounds(i::Interval) end Base.in(u, i::Interval) = i.lb <= u <= i.ub + +hi(X::Interval) = X.ub +lo(X::Interval) = X.lb +hi(X::Real) = X +lo(X::Real) = X \ No newline at end of file diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 1f3f148e4..e4431beaa 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -1,5 +1,3 @@ -using RecipesBase - DEFAULT_ALPHA = 0.2 DEFAULT_LABEL = "" DEFAULT_GRID = false @@ -10,7 +8,8 @@ DEFAULT_COLOUR_PDF = :blue DEFAULT_COLOUR_UPPER = :red DEFAULT_COLOUR_LOWER = :black -DEFAULT_PLOT_RANGE_EXTEND = 0.2 +DEFAULT_PLOT_RANGE_EXTEND_DENSITY = 0.1 +DEFAULT_PLOT_RANGE_EXTEND = 0.4 DEFAULT_PLOT_RANGE_INTERVAL = 0.4 DEFAULT_PLOT_GRID_NUMBER = 500 DEFAULT_FONT_SIZE = 18 @@ -27,13 +26,10 @@ DEFAULT_TICK_SIZE = 12 lo_grid = quantile(x, 0.001) hi_grid = quantile(x, 0.999) - lo_grid = x.lb - hi_grid = x.ub - width = (hi_grid + lo_grid)/2 - lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) - hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) + lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) + hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) pdf_evals = pdf.(Ref(x), x_grid) @@ -65,13 +61,15 @@ end width = (hi_grid + lo_grid)/2 - lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_INTERVAL) - hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_INTERVAL) + plot_lo = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) + plot_hi = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) cdf_lo = x_grid .>= x.ub - cdf_hi = x_grid .>= x.lb + cdf_hi = x_grid .> x.lb + + xlims --> (plot_lo, plot_hi) @series begin fillrange := cdf_hi @@ -103,8 +101,8 @@ end ylabel --> "cdf" xlabel --> x.name - lo_grid = quantile(x, 0.001)[1] - hi_grid = quantile(x, 0.999)[2] + lo_grid = quantile(x, 0.001).lb + hi_grid = quantile(x, 0.999).ub width = (hi_grid + lo_grid)/2 @@ -136,7 +134,23 @@ end end end +@recipe function _plot(x::Vector{T}) where T <: UQInput + + x_no_params = filter(x -> !isa(x, Parameter), x) + + N_inputs = length(x_no_params) + cols = ceil(Int, sqrt(N_inputs)) # Calculate the number of columns + rows = ceil(Int, N_inputs / cols) # Calculate the number of rows needed + layout := grid(rows, cols) # Create a grid layout + + for i = 1:N_inputs + @series begin + subplot := i + x_no_params[i] + end + end +end ### # This code is a modified version of the plot recipe from IntervalArithmetic.jl # https://github.com/JuliaIntervals/IntervalArithmetic.jl From 10ba8249c69732bfafdd1952efce2a6e9f59725f Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Mon, 22 Jul 2024 10:29:36 +0100 Subject: [PATCH 03/14] fix plotting width --- src/plotting/plot_recipes.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index e4431beaa..329369ca0 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -8,8 +8,8 @@ DEFAULT_COLOUR_PDF = :blue DEFAULT_COLOUR_UPPER = :red DEFAULT_COLOUR_LOWER = :black -DEFAULT_PLOT_RANGE_EXTEND_DENSITY = 0.1 -DEFAULT_PLOT_RANGE_EXTEND = 0.4 +DEFAULT_PLOT_RANGE_EXTEND_DENSITY = 0.2 +DEFAULT_PLOT_RANGE_EXTEND = 0.2 DEFAULT_PLOT_RANGE_INTERVAL = 0.4 DEFAULT_PLOT_GRID_NUMBER = 500 DEFAULT_FONT_SIZE = 18 @@ -26,7 +26,7 @@ DEFAULT_TICK_SIZE = 12 lo_grid = quantile(x, 0.001) hi_grid = quantile(x, 0.999) - width = (hi_grid + lo_grid)/2 + width = hi_grid - lo_grid lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) @@ -59,17 +59,17 @@ end lo_grid = x.lb hi_grid = x.ub - width = (hi_grid + lo_grid)/2 + width = hi_grid - lo_grid - plot_lo = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) - plot_hi = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) + plot_lo = lo_grid - abs(width * DEFAULT_PLOT_RANGE_INTERVAL) + plot_hi = hi_grid + abs(width * DEFAULT_PLOT_RANGE_INTERVAL) + + xlims := (plot_lo, plot_hi) x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) cdf_lo = x_grid .>= x.ub cdf_hi = x_grid .> x.lb - - xlims --> (plot_lo, plot_hi) @series begin fillrange := cdf_hi @@ -104,7 +104,7 @@ end lo_grid = quantile(x, 0.001).lb hi_grid = quantile(x, 0.999).ub - width = (hi_grid + lo_grid)/2 + width = hi_grid - lo_grid lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) From ae2760c0ba780965f0c7afad44a2ae91ef100018 Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Mon, 22 Jul 2024 13:01:04 +0100 Subject: [PATCH 04/14] adds option to plot in cdf for random variables --- src/plotting/plot_recipes.jl | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 329369ca0..c9bb8e378 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -2,6 +2,7 @@ DEFAULT_ALPHA = 0.2 DEFAULT_LABEL = "" DEFAULT_GRID = false DEFAULT_LEGEND = false +DEFAULT_CDF = false DEFAULT_DISTRIBUTION = :pdf DEFAULT_FILL = :gray DEFAULT_COLOUR_PDF = :blue @@ -15,13 +16,17 @@ DEFAULT_PLOT_GRID_NUMBER = 500 DEFAULT_FONT_SIZE = 18 DEFAULT_TICK_SIZE = 12 - -@recipe function _plot(x::RandomVariable) +### +# Plots for UQInputs +### +@recipe function _plot(x::RandomVariable; cdf_on = DEFAULT_CDF) grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND - ylabel --> "pdf" xlabel --> x.name + cdf_on ? ylabel --> "cdf" : ylabel --> "pdf" + + # cdf_on --> DEFAULT_CDF lo_grid = quantile(x, 0.001) hi_grid = quantile(x, 0.999) @@ -32,20 +37,28 @@ DEFAULT_TICK_SIZE = 12 hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) - pdf_evals = pdf.(Ref(x), x_grid) + + if cdf_on + distribution_evals = cdf.(Ref(x), x_grid) + else + distribution_evals = pdf.(Ref(x), x_grid) + end - @series begin - fillrange := pdf_evals - color := DEFAULT_FILL - fillalpha := DEFAULT_ALPHA - x_grid, zeros(length(x_grid)) + if ~cdf_on + @series begin + fillrange := distribution_evals + color := DEFAULT_FILL + fillalpha := DEFAULT_ALPHA + x_grid, zeros(length(x_grid)) + end end + @series begin color --> DEFAULT_COLOUR_PDF alpha := 1 label := "" - x_grid, pdf_evals + x_grid, distribution_evals end end From 351efd3fdc89d89f4af5b3ec4e3a64380b04174e Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Mon, 22 Jul 2024 13:35:57 +0100 Subject: [PATCH 05/14] adds plot recipie for sample of a p-box --- src/plotting/plot_recipes.jl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index c9bb8e378..57068a74c 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -203,3 +203,38 @@ end xs, ys end + +### +# Plots for samples of data frames +### + +@recipe function _plot(x::Vector{Interval}) + + if length(unique(x))==1 + return x[1] + else + grid --> DEFAULT_GRID + legend --> DEFAULT_LEGEND + + xlabel --> x[1].name + ylabel --> "cdf" + N_samples = length(x) + + lows = sort(lo.(x)) + his = sort(hi.(x)) + + is = range(0, 1, length = N_samples) + + @series begin + seriestype := :steppre + color --> DEFAULT_COLOUR_LOWER + lows, is + end + + @series begin + seriestype := :steppost + color --> DEFAULT_COLOUR_UPPER + his, is + end + end +end \ No newline at end of file From c5edd4f5e0d5fda6feff0a0c1b3389a6c7ce8def Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Wed, 13 Aug 2025 14:09:02 +0100 Subject: [PATCH 06/14] update Project.toml --- Project.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 41afa98c2..ea0bf3c8a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,15 +1,11 @@ name = "UncertaintyQuantification" uuid = "7183a548-a887-11e9-15ce-a56ab60bad7a" -<<<<<<< HEAD -authors = ["Jasper Behrensdorf ", "Ander Gray "] -version = "0.10.0" -======= + authors = [ "Jasper Behrensdorf ", "Ander Gray ", ] version = "0.12.0" ->>>>>>> master [deps] Bootstrap = "e28b5b4c-05e8-5b66-bc03-6f0c0a0a06e0" From f495fe8f7993f203932edc768fb83d7677f4a6d8 Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Wed, 13 Aug 2025 14:26:00 +0100 Subject: [PATCH 07/14] working simple plots after merge --- Project.toml | 9 +++------ demo/plotting/plot_inputs.jl | 28 ++++++++++++++++++++++++++++ src/inputs/imprecise/interval.jl | 12 +++++------- src/plotting/plot_recipes.jl | 8 ++++---- 4 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 demo/plotting/plot_inputs.jl diff --git a/Project.toml b/Project.toml index ea0bf3c8a..d497c1d28 100644 --- a/Project.toml +++ b/Project.toml @@ -1,10 +1,6 @@ name = "UncertaintyQuantification" uuid = "7183a548-a887-11e9-15ce-a56ab60bad7a" - -authors = [ - "Jasper Behrensdorf ", - "Ander Gray ", -] +authors = ["Jasper Behrensdorf ", "Ander Gray "] version = "0.12.0" [deps] @@ -23,8 +19,8 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MeshAdaptiveDirectSearch = "f4d74008-4565-11e9-04bd-4fe404e6a92a" Monomials = "272bfe72-f66c-432f-a94d-600f29493792" Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70" -Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Optim = "429524aa-4258-5aef-a3af-852621145aeb" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" @@ -49,6 +45,7 @@ MeshAdaptiveDirectSearch = "0.1.0" Monomials = "1.0" Mustache = "1.0" Optim = "1.9.4" +Plots = "1.40.18" Primes = "0.5" QuadGK = "2.11.1" QuasiMonteCarlo = "0.3" diff --git a/demo/plotting/plot_inputs.jl b/demo/plotting/plot_inputs.jl new file mode 100644 index 000000000..50f82d733 --- /dev/null +++ b/demo/plotting/plot_inputs.jl @@ -0,0 +1,28 @@ +using UncertaintyQuantification, Plots + +X1 = RandomVariable(ProbabilityBox{Normal}(Dict(:μ => Interval(-1, 2), :σ => 1)), :X1) +X2 = RandomVariable(ProbabilityBox{Normal}(Dict(:μ => Interval(-1, 2), :σ => 2)), :X2) +X3 = IntervalVariable(-1, 2, :s) +h = RandomVariable(Normal(0.24, 0.01), :h) # height + +plot(X1) # p-box +plot(X1, color = "red") # red p-box +plot(X3) # Interval +plot(h) # distribution + +inputs = [X1, X2, X3, h] + +plot(inputs) # Everything together + +samples = sample(inputs, 200) + +plot(X1) +plot!(samples.X1) # Samples ecdf samples of X1 + +plot(samples.X1[1], samples.X2[1]) # Plots 2D box + +plot(samples.X1, samples.X2) # Plots bivariate random sets of X1 and X2 + +df = sample(inputs, 200) + + diff --git a/src/inputs/imprecise/interval.jl b/src/inputs/imprecise/interval.jl index f2cf0ccd1..88a146fdd 100644 --- a/src/inputs/imprecise/interval.jl +++ b/src/inputs/imprecise/interval.jl @@ -44,6 +44,11 @@ function bounds(i::Interval) return i.lb, i.ub end +hi(X::Interval) = X.ub +lo(X::Interval) = X.lb +hi(X::Real) = X +lo(X::Real) = X + """ IntervalVariable(lb::Real, ub::Real, name::Symbol) @@ -103,13 +108,6 @@ function bounds(i::IntervalVariable) return i.lb, i.ub end -Base.in(u, i::Interval) = i.lb <= u <= i.ub - -hi(X::Interval) = X.ub -lo(X::Interval) = X.lb -hi(X::Real) = X -lo(X::Real) = X - Base.in(u, i::IntervalVariable) = i.lb <= u <= i.ub mean(i::IntervalVariable) = Interval(i) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 57068a74c..78d513e7e 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -19,7 +19,7 @@ DEFAULT_TICK_SIZE = 12 ### # Plots for UQInputs ### -@recipe function _plot(x::RandomVariable; cdf_on = DEFAULT_CDF) +@recipe function _plot(x::RandomVariable{T}; cdf_on = DEFAULT_CDF) where {T <: UnivariateDistribution} grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND @@ -62,7 +62,7 @@ DEFAULT_TICK_SIZE = 12 end end -@recipe function _plot(x::Interval) +@recipe function _plot(x::IntervalVariable) grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND @@ -107,7 +107,7 @@ end end -@recipe function _plot(x::ProbabilityBox) +@recipe function _plot(x::RandomVariable{T}) where {T <: ProbabilityBox} grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND @@ -216,7 +216,7 @@ end grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND - xlabel --> x[1].name + # xlabel --> x[1].name ylabel --> "cdf" N_samples = length(x) From 0993d66318d41f2ac197310a07fa9a8c8d86cdad Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Thu, 23 Oct 2025 15:34:58 +0100 Subject: [PATCH 08/14] remove plots from deps --- Project.toml | 2 -- src/UncertaintyQuantification.jl | 1 - 2 files changed, 3 deletions(-) diff --git a/Project.toml b/Project.toml index d497c1d28..f906cf512 100644 --- a/Project.toml +++ b/Project.toml @@ -20,7 +20,6 @@ MeshAdaptiveDirectSearch = "f4d74008-4565-11e9-04bd-4fe404e6a92a" Monomials = "272bfe72-f66c-432f-a94d-600f29493792" Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70" Optim = "429524aa-4258-5aef-a3af-852621145aeb" -Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" @@ -45,7 +44,6 @@ MeshAdaptiveDirectSearch = "0.1.0" Monomials = "1.0" Mustache = "1.0" Optim = "1.9.4" -Plots = "1.40.18" Primes = "0.5" QuadGK = "2.11.1" QuasiMonteCarlo = "0.3" diff --git a/src/UncertaintyQuantification.jl b/src/UncertaintyQuantification.jl index c59656974..20888bcfb 100644 --- a/src/UncertaintyQuantification.jl +++ b/src/UncertaintyQuantification.jl @@ -21,7 +21,6 @@ using Random using Reexport using Roots using StatsBase -using Plots using RecipesBase @reexport using Distributions From 273e045073085b2960874bfe14556868c928deb0 Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Thu, 23 Oct 2025 16:12:06 +0100 Subject: [PATCH 09/14] adds line alpha and width to bivariate intervals --- demo/plotting/plot_inputs.jl | 4 ---- src/plotting/plot_recipes.jl | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/demo/plotting/plot_inputs.jl b/demo/plotting/plot_inputs.jl index 50f82d733..1168c0de9 100644 --- a/demo/plotting/plot_inputs.jl +++ b/demo/plotting/plot_inputs.jl @@ -22,7 +22,3 @@ plot!(samples.X1) # Samples ecdf samples of X1 plot(samples.X1[1], samples.X2[1]) # Plots 2D box plot(samples.X1, samples.X2) # Plots bivariate random sets of X1 and X2 - -df = sample(inputs, 200) - - diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 78d513e7e..7176cec1b 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -9,6 +9,9 @@ DEFAULT_COLOUR_PDF = :blue DEFAULT_COLOUR_UPPER = :red DEFAULT_COLOUR_LOWER = :black +DEFAULT_INTERVAL_WIDTH=1.5 +DEFAULT_INTERVAL_EDGE_ALPHA=1 + DEFAULT_PLOT_RANGE_EXTEND_DENSITY = 0.2 DEFAULT_PLOT_RANGE_EXTEND = 0.2 DEFAULT_PLOT_RANGE_INTERVAL = 0.4 @@ -155,7 +158,7 @@ end cols = ceil(Int, sqrt(N_inputs)) # Calculate the number of columns rows = ceil(Int, N_inputs / cols) # Calculate the number of rows needed - layout := grid(rows, cols) # Create a grid layout + layout := (rows, cols) # Create a grid layout for i = 1:N_inputs @series begin @@ -170,11 +173,17 @@ end ### # Plot a 2D IntervalBox: -@recipe function _plot(x::Interval, y::Interval) #; customcolor = :green, alpha=0.5) +@recipe function _plot(x::Interval, y::Interval) seriesalpha --> DEFAULT_ALPHA seriestype := :shape + label := false + + linecolor --> :black # Explicitly set edge color + linewidth --> DEFAULT_INTERVAL_WIDTH # Make edges more visible + linealpha --> DEFAULT_INTERVAL_EDGE_ALPHA + x = [x.lb, x.ub, x.ub, x.lb] y = [y.lb, y.lb, y.ub, y.ub] @@ -184,8 +193,15 @@ end # Plot a vector of 2D IntervalBoxes: @recipe function _plot(xx::Vector{T}, yy::Vector{T}) where T<:Interval + seriesalpha --> DEFAULT_ALPHA seriestype := :shape + label := false + + linecolor := :black # Explicitly set edge color + linewidth --> DEFAULT_INTERVAL_WIDTH # Make edges more visible + linealpha --> DEFAULT_INTERVAL_EDGE_ALPHA + xs = Float64[] ys = Float64[] @@ -199,7 +215,6 @@ end end - seriesalpha --> DEFAULT_ALPHA xs, ys end From cc319698ba77e60774ed9db91b3fbec5056d7bcd Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Thu, 23 Oct 2025 16:32:24 +0100 Subject: [PATCH 10/14] adds basic plot tests --- test/Project.toml | 1 + test/plotting/plotting.jl | 60 +++++++++++++++++++++++++++++++++++++++ test/runtests.jl | 3 ++ 3 files changed, 64 insertions(+) create mode 100644 test/plotting/plotting.jl diff --git a/test/Project.toml b/test/Project.toml index f36f601fe..af12538e8 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -4,6 +4,7 @@ Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" HCubature = "19dc6840-f33b-545b-b366-655c7e3ffd49" HypothesisTests = "09f84164-cd44-5f33-b23f-e6b0d136a0d5" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" QuasiMonteCarlo = "8a4e6c94-4038-4cdc-81c3-7e6ffdb2a71b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" diff --git a/test/plotting/plotting.jl b/test/plotting/plotting.jl new file mode 100644 index 000000000..62039e785 --- /dev/null +++ b/test/plotting/plotting.jl @@ -0,0 +1,60 @@ +@testset "Plotting Recipes" begin + + @testset "RandomVariable PDF Plot" begin + rv = RandomVariable(Normal(0, 1), :X) + plt = plot(rv; cdf_on=false) + @test typeof(plt) <: Plots.Plot + @test plt.series_list[1][:seriestype] == :path + @test plt.series_list[2][:seriestype] == :path + end + + @testset "RandomVariable CDF Plot" begin + rv = RandomVariable(Normal(0, 1), :X) + plt = plot(rv; cdf_on=true) + @test typeof(plt) <: Plots.Plot + end + + @testset "IntervalVariable Plot" begin + iv = IntervalVariable(1.0, 2.0, :Y) + plt = plot(iv) + @test typeof(plt) <: Plots.Plot + @test length(plt.series_list) == 3 + @test plt.series_list[1][:fillalpha] == 0.2 + end + + @testset "ProbabilityBox Plot" begin + pb = RandomVariable(ProbabilityBox{Normal}(Dict(:μ => Interval(-1, 2), :σ => 2)), :X2) + plt = plot(pb) + @test typeof(plt) <: Plots.Plot + @test length(plt.series_list) == 3 + end + + @testset "Vector of UQInputs Plot" begin + inputs = [RandomVariable(Normal(0,1), :A), IntervalVariable(1.0, 2.0, :B)] + plt = plot(inputs) + @test typeof(plt) <: Plots.Plot + @test plt.layout isa Plots.GridLayout + end + + @testset "2D IntervalBox Plot" begin + x = Interval(1.0, 2.0) + y = Interval(3.0, 4.0) + plt = plot(x, y) + @test typeof(plt) <: Plots.Plot + @test plt.series_list[1][:seriestype] == :shape + end + + @testset "Vector of IntervalBoxes Plot" begin + xs = [Interval(1.0, 2.0), Interval(2.0, 3.0)] + ys = [Interval(3.0, 4.0), Interval(4.0, 5.0)] + plt = plot(xs, ys) + @test typeof(plt) <: Plots.Plot + @test plt.series_list[1][:seriestype] == :shape + end + + @testset "Vector of Intervals Plot" begin + intervals = [Interval(1.0, 2.0), Interval(1.5, 2.5), Interval(2.0, 3.0)] + plt = plot(intervals) + @test typeof(plt) <: Plots.Plot + end +end diff --git a/test/runtests.jl b/test/runtests.jl index eb3e174ef..499938f97 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,6 +7,7 @@ using QuasiMonteCarlo using Random using StatsBase: fit, Histogram, corkendall using Test +using Plots using UncertaintyQuantification include("inputs/empiricaldistribution.jl") @@ -49,6 +50,8 @@ include("simulations/subset.jl") include("util/fourier-transform.jl") +include("plotting/plotting.jl") + if Sys.islinux() HPC = false HPC_account = "HPC_account_1" From 099d6f3cd224f7d36369d0efe1ab74def171fc50 Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Tue, 28 Oct 2025 16:04:48 +0000 Subject: [PATCH 11/14] adds default julia colours --- src/plotting/plot_recipes.jl | 176 ++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 76 deletions(-) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 7176cec1b..258d9e77c 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -1,8 +1,9 @@ DEFAULT_ALPHA = 0.2 DEFAULT_LABEL = "" DEFAULT_GRID = false -DEFAULT_LEGEND = false +DEFAULT_LEGEND = true DEFAULT_CDF = false +DEFAULT_FILL_DISTRIBUTION=true DEFAULT_DISTRIBUTION = :pdf DEFAULT_FILL = :gray DEFAULT_COLOUR_PDF = :blue @@ -12,6 +13,8 @@ DEFAULT_COLOUR_LOWER = :black DEFAULT_INTERVAL_WIDTH=1.5 DEFAULT_INTERVAL_EDGE_ALPHA=1 +DEFAULT_DISTRIBUTION_WIDTH=2 + DEFAULT_PLOT_RANGE_EXTEND_DENSITY = 0.2 DEFAULT_PLOT_RANGE_EXTEND = 0.2 DEFAULT_PLOT_RANGE_INTERVAL = 0.4 @@ -22,55 +25,57 @@ DEFAULT_TICK_SIZE = 12 ### # Plots for UQInputs ### -@recipe function _plot(x::RandomVariable{T}; cdf_on = DEFAULT_CDF) where {T <: UnivariateDistribution} - +@recipe function _plot( + x::RandomVariable{T}; cdf_on=DEFAULT_CDF +) where {T<:UnivariateDistribution} grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND - xlabel --> x.name - cdf_on ? ylabel --> "cdf" : ylabel --> "pdf" - - # cdf_on --> DEFAULT_CDF - - lo_grid = quantile(x, 0.001) - hi_grid = quantile(x, 0.999) - - width = hi_grid - lo_grid + label --> String(x.name) + (cdf_on ? ylabel --> "cdf" : ylabel --> "pdf") + seriescolor --> :auto - lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) - hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) + lo = quantile(x, 0.001) + hi = quantile(x, 0.999) + w = hi - lo + lo -= abs(w * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) + hi += abs(w * DEFAULT_PLOT_RANGE_EXTEND_DENSITY) - x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) + xs = range(lo, hi, DEFAULT_PLOT_GRID_NUMBER) + ys = cdf_on ? cdf.(Ref(x), xs) : pdf.(Ref(x), xs) - if cdf_on - distribution_evals = cdf.(Ref(x), x_grid) - else - distribution_evals = pdf.(Ref(x), x_grid) + # Primary line: either cdf or pdf + @series begin + seriestype := :path + fill := nothing + alpha --> 1 + linewidth --> DEFAULT_DISTRIBUTION_WIDTH + label --> String(x.name) + xs, ys end - - if ~cdf_on + + # Optional fill for PDF only: reuse color, don't advance palette + if !cdf_on @series begin - fillrange := distribution_evals - color := DEFAULT_FILL - fillalpha := DEFAULT_ALPHA - x_grid, zeros(length(x_grid)) + primary := false # <-- reuse the color from the primary line + seriestype := :path + fillrange := 0 # fill down to baseline + fillcolor := :match + fillalpha --> DEFAULT_ALPHA + linewidth --> 0 # fill only; no extra line + label := "" + xs, ys end end - - - @series begin - color --> DEFAULT_COLOUR_PDF - alpha := 1 - label := "" - x_grid, distribution_evals - end end @recipe function _plot(x::IntervalVariable) - + # --- plot-level defaults (soft) --- grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND ylabel --> "cdf" - xlabel --> x.name + label --> String(x.name) # single legend entry + + seriescolor --> :auto lo_grid = x.lb hi_grid = x.ub @@ -86,87 +91,111 @@ end cdf_lo = x_grid .>= x.ub cdf_hi = x_grid .> x.lb - + + # Plot upper cdf (primary, inherits colour and label) @series begin - fillrange := cdf_hi - color := DEFAULT_FILL - fillalpha := DEFAULT_ALPHA - x_grid, cdf_lo + seriestype := :path + alpha --> 1 + linewidth --> DEFAULT_DISTRIBUTION_WIDTH + x_grid, cdf_hi end + # Plot lower cdf @series begin - color --> DEFAULT_COLOUR_LOWER - alpha := 1 + primary := false + seriestype := :path + alpha --> 1 label := "" + linewidth --> DEFAULT_DISTRIBUTION_WIDTH x_grid, cdf_lo end + # Plot fill @series begin - color --> DEFAULT_COLOUR_UPPER - alpha := 1 + primary := false + seriestype := :path + fillcolor := :match # match this series' line color + fillrange := cdf_hi + color := DEFAULT_FILL + fillalpha := DEFAULT_ALPHA + linewidth --> 0 # draw fill only here label := "" - x_grid, cdf_hi + x_grid, cdf_lo end - end -@recipe function _plot(x::RandomVariable{T}) where {T <: ProbabilityBox} - +@recipe function _plot(x::RandomVariable{T}) where {T<:ProbabilityBox} + # --- plot-level defaults (soft) --- grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND ylabel --> "cdf" - xlabel --> x.name + label --> String(x.name) # single legend entry + + seriescolor --> :auto lo_grid = quantile(x, 0.001).lb hi_grid = quantile(x, 0.999).ub - width = hi_grid - lo_grid - lo_grid = lo_grid - abs(width * DEFAULT_PLOT_RANGE_EXTEND) hi_grid = hi_grid + abs(width * DEFAULT_PLOT_RANGE_EXTEND) x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) cdf_evals = cdf.(Ref(x), x_grid) + # Plot upper cdf (primary, inherits colour and label) @series begin - fillrange := hi.(cdf_evals) - color := DEFAULT_FILL - fillalpha := DEFAULT_ALPHA - x_grid, lo.(cdf_evals) + seriestype := :path + alpha --> 1 + linewidth --> DEFAULT_DISTRIBUTION_WIDTH + x_grid, hi.(cdf_evals) end + # Plot lower cdf @series begin - color --> DEFAULT_COLOUR_LOWER - alpha := 1 + primary := false + seriestype := :path + alpha --> 1 + linewidth --> DEFAULT_DISTRIBUTION_WIDTH label := "" x_grid, lo.(cdf_evals) end + # Plot fill @series begin - color --> DEFAULT_COLOUR_UPPER - alpha := 1 + primary := false + seriestype := :path + fillcolor := :match # match this series' line color + fillrange := hi.(cdf_evals) + fillalpha --> DEFAULT_ALPHA + linewidth --> 0 # draw fill only here label := "" - x_grid, hi.(cdf_evals) + x_grid, lo.(cdf_evals) end end -@recipe function _plot(x::Vector{T}) where T <: UQInput +using RecipesBase - x_no_params = filter(x -> !isa(x, Parameter), x) +@recipe function _plot(x::Vector{T}) where {T<:UQInput} + # Filter out Parameter objects + x_no_params = filter(xi -> !isa(xi, Parameter), x) - N_inputs = length(x_no_params) + N = length(x_no_params) + cols = ceil(Int, sqrt(N)) + rows = ceil(Int, N / cols) + layout := (rows, cols) - cols = ceil(Int, sqrt(N_inputs)) # Calculate the number of columns - rows = ceil(Int, N_inputs / cols) # Calculate the number of rows needed - layout := (rows, cols) # Create a grid layout + # Choose a grid palette once (users can still override via plot(...; palette=...)) + # palette --> :default # or :default, :Dark2_8, etc. - for i = 1:N_inputs + for i in 1:N @series begin subplot := i + seriescolor --> i # <-- panel i uses the i-th color from the current palette x_no_params[i] end end end + ### # This code is a modified version of the plot recipe from IntervalArithmetic.jl # https://github.com/JuliaIntervals/IntervalArithmetic.jl @@ -174,7 +203,6 @@ end # Plot a 2D IntervalBox: @recipe function _plot(x::Interval, y::Interval) - seriesalpha --> DEFAULT_ALPHA seriestype := :shape @@ -191,8 +219,7 @@ end end # Plot a vector of 2D IntervalBoxes: -@recipe function _plot(xx::Vector{T}, yy::Vector{T}) where T<:Interval - +@recipe function _plot(xx::Vector{T}, yy::Vector{T}) where {T<:Interval} seriesalpha --> DEFAULT_ALPHA seriestype := :shape @@ -206,17 +233,15 @@ end ys = Float64[] # build up coords: # (alternative: use @series) - for i = 1:length(xx) + for i in 1:length(xx) (x, y) = (xx[i], yy[i]) # use NaNs to separate append!(xs, [x.lb, x.ub, x.ub, x.lb, NaN]) append!(ys, [y.lb, y.lb, y.ub, y.ub, NaN]) - end xs, ys - end ### @@ -224,7 +249,6 @@ end ### @recipe function _plot(x::Vector{Interval}) - if length(unique(x))==1 return x[1] else @@ -238,7 +262,7 @@ end lows = sort(lo.(x)) his = sort(hi.(x)) - is = range(0, 1, length = N_samples) + is = range(0, 1, length=N_samples) @series begin seriestype := :steppre @@ -252,4 +276,4 @@ end his, is end end -end \ No newline at end of file +end From 8c060a4ba250d1c014726c6d59d280d8b5bd7f2d Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Tue, 28 Oct 2025 16:13:28 +0000 Subject: [PATCH 12/14] adds option for plot fill --- src/plotting/plot_recipes.jl | 53 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 258d9e77c..9ffb0a383 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -4,6 +4,7 @@ DEFAULT_GRID = false DEFAULT_LEGEND = true DEFAULT_CDF = false DEFAULT_FILL_DISTRIBUTION=true +DEFAULT_FILL_IMPRECISE=true DEFAULT_DISTRIBUTION = :pdf DEFAULT_FILL = :gray DEFAULT_COLOUR_PDF = :blue @@ -26,7 +27,7 @@ DEFAULT_TICK_SIZE = 12 # Plots for UQInputs ### @recipe function _plot( - x::RandomVariable{T}; cdf_on=DEFAULT_CDF + x::RandomVariable{T}; cdf_on=DEFAULT_CDF, shade=DEFAULT_FILL_DISTRIBUTION ) where {T<:UnivariateDistribution} grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND @@ -54,7 +55,7 @@ DEFAULT_TICK_SIZE = 12 end # Optional fill for PDF only: reuse color, don't advance palette - if !cdf_on + if !cdf_on && shade @series begin primary := false # <-- reuse the color from the primary line seriestype := :path @@ -68,7 +69,7 @@ DEFAULT_TICK_SIZE = 12 end end -@recipe function _plot(x::IntervalVariable) +@recipe function _plot(x::IntervalVariable; shade=DEFAULT_FILL_IMPRECISE) # --- plot-level defaults (soft) --- grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND @@ -111,20 +112,24 @@ end end # Plot fill - @series begin - primary := false - seriestype := :path - fillcolor := :match # match this series' line color - fillrange := cdf_hi - color := DEFAULT_FILL - fillalpha := DEFAULT_ALPHA - linewidth --> 0 # draw fill only here - label := "" - x_grid, cdf_lo + if shade + @series begin + primary := false + seriestype := :path + fillcolor := :match # match this series' line color + fillrange := cdf_hi + color := DEFAULT_FILL + fillalpha := DEFAULT_ALPHA + linewidth --> 0 # draw fill only here + label := "" + x_grid, cdf_lo + end end end -@recipe function _plot(x::RandomVariable{T}) where {T<:ProbabilityBox} +@recipe function _plot( + x::RandomVariable{T}; shade=DEFAULT_FILL_IMPRECISE +) where {T<:ProbabilityBox} # --- plot-level defaults (soft) --- grid --> DEFAULT_GRID legend --> DEFAULT_LEGEND @@ -161,15 +166,17 @@ end end # Plot fill - @series begin - primary := false - seriestype := :path - fillcolor := :match # match this series' line color - fillrange := hi.(cdf_evals) - fillalpha --> DEFAULT_ALPHA - linewidth --> 0 # draw fill only here - label := "" - x_grid, lo.(cdf_evals) + if shade + @series begin + primary := false + seriestype := :path + fillcolor := :match # match this series' line color + fillrange := hi.(cdf_evals) + fillalpha --> DEFAULT_ALPHA + linewidth --> 0 # draw fill only here + label := "" + x_grid, lo.(cdf_evals) + end end end From 0c93a012206d4ffc80f28d70f70eb9c724e5b1c7 Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Tue, 28 Oct 2025 16:21:58 +0000 Subject: [PATCH 13/14] update plotting tests, and add hi/lo tests --- test/inputs/imprecise/interval.jl | 8 ++++++++ test/plotting/plotting.jl | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/inputs/imprecise/interval.jl b/test/inputs/imprecise/interval.jl index 54d202a10..6c0fe10a9 100644 --- a/test/inputs/imprecise/interval.jl +++ b/test/inputs/imprecise/interval.jl @@ -1,3 +1,5 @@ +using UncertaintyQuantification: hi, lo + @testset "Interval" begin name = :l lb = 0.14 @@ -16,6 +18,12 @@ @test !(0.17 ∈ interval) @test sprint(show, interval) == "[0.14, 0.16]" + + @test hi(interval) == interval.ub + @test lo(interval) == interval.lb + + @test hi(2.0) == 2.0 + @test lo(2.0) == 2.0 end @testset "IntervalVariable" begin diff --git a/test/plotting/plotting.jl b/test/plotting/plotting.jl index 62039e785..200743349 100644 --- a/test/plotting/plotting.jl +++ b/test/plotting/plotting.jl @@ -19,7 +19,6 @@ plt = plot(iv) @test typeof(plt) <: Plots.Plot @test length(plt.series_list) == 3 - @test plt.series_list[1][:fillalpha] == 0.2 end @testset "ProbabilityBox Plot" begin From 59b06272d8ae6b2fe471ef2b3afee9fcc74041e7 Mon Sep 17 00:00:00 2001 From: Ander Gray Date: Tue, 28 Oct 2025 16:51:24 +0000 Subject: [PATCH 14/14] allow user to change grid layout, and remove xlim setting for intervals --- src/plotting/plot_recipes.jl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/plotting/plot_recipes.jl b/src/plotting/plot_recipes.jl index 9ffb0a383..eeb3ac1d4 100644 --- a/src/plotting/plot_recipes.jl +++ b/src/plotting/plot_recipes.jl @@ -83,11 +83,9 @@ end width = hi_grid - lo_grid - plot_lo = lo_grid - abs(width * DEFAULT_PLOT_RANGE_INTERVAL) + plot_lo = lo_grid - abs(width * DEFAULT_PLOT_RANGE_INTERVAL) # For adding a slight width to the left and right side of the interval plot plot_hi = hi_grid + abs(width * DEFAULT_PLOT_RANGE_INTERVAL) - xlims := (plot_lo, plot_hi) - x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) cdf_lo = x_grid .>= x.ub @@ -111,6 +109,16 @@ end x_grid, cdf_lo end + # Add invisible lines so interval bounds don't touch plot boundaries + @series begin + primary := false + seriestype := :path + alpha --> 0 + label := "" + linewidth --> 0 + range(plot_lo, plot_hi, 100), zeros(100) + end + # Plot fill if shade @series begin @@ -180,8 +188,6 @@ end end end -using RecipesBase - @recipe function _plot(x::Vector{T}) where {T<:UQInput} # Filter out Parameter objects x_no_params = filter(xi -> !isa(xi, Parameter), x) @@ -189,7 +195,7 @@ using RecipesBase N = length(x_no_params) cols = ceil(Int, sqrt(N)) rows = ceil(Int, N / cols) - layout := (rows, cols) + layout --> (rows, cols) # Choose a grid palette once (users can still override via plot(...; palette=...)) # palette --> :default # or :default, :Dark2_8, etc.