-
Notifications
You must be signed in to change notification settings - Fork 13
Adds basic plots #279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AnderGray
wants to merge
17
commits into
master
Choose a base branch
from
plotting_pr_clean
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Adds basic plots #279
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
768c2f1
initial commit for plotting recipies
AnderGray c64b6e4
merge with master
AnderGray bdea02a
working plotting with UQInputs vector
AnderGray 10ba824
fix plotting width
AnderGray ae2760c
adds option to plot in cdf for random variables
AnderGray 351efd3
adds plot recipie for sample of a p-box
AnderGray 22133c6
merge master into plotting
AnderGray c5edd4f
update Project.toml
AnderGray f495fe8
working simple plots after merge
AnderGray 0993d66
remove plots from deps
AnderGray c6bd560
merge with master
AnderGray 273e045
adds line alpha and width to bivariate intervals
AnderGray cc31969
adds basic plot tests
AnderGray 099d6f3
adds default julia colours
AnderGray 8c060a4
adds option for plot fill
AnderGray 0c93a01
update plotting tests, and add hi/lo tests
AnderGray 59b0627
allow user to change grid layout, and remove xlim setting for intervals
AnderGray File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,292 @@ | ||
| DEFAULT_ALPHA = 0.2 | ||
| DEFAULT_LABEL = "" | ||
| 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 | ||
| DEFAULT_COLOUR_UPPER = :red | ||
| 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 | ||
| DEFAULT_PLOT_GRID_NUMBER = 500 | ||
| DEFAULT_FONT_SIZE = 18 | ||
| DEFAULT_TICK_SIZE = 12 | ||
|
|
||
| ### | ||
| # Plots for UQInputs | ||
| ### | ||
| @recipe function _plot( | ||
| x::RandomVariable{T}; cdf_on=DEFAULT_CDF, shade=DEFAULT_FILL_DISTRIBUTION | ||
| ) where {T<:UnivariateDistribution} | ||
| grid --> DEFAULT_GRID | ||
| legend --> DEFAULT_LEGEND | ||
| label --> String(x.name) | ||
| (cdf_on ? ylabel --> "cdf" : ylabel --> "pdf") | ||
| seriescolor --> :auto | ||
|
|
||
| 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) | ||
|
|
||
| xs = range(lo, hi, DEFAULT_PLOT_GRID_NUMBER) | ||
| ys = cdf_on ? cdf.(Ref(x), xs) : pdf.(Ref(x), xs) | ||
|
|
||
| # 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 | ||
|
|
||
| # Optional fill for PDF only: reuse color, don't advance palette | ||
| if !cdf_on && shade | ||
| @series begin | ||
| 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 | ||
| end | ||
|
|
||
| @recipe function _plot(x::IntervalVariable; shade=DEFAULT_FILL_IMPRECISE) | ||
| # --- plot-level defaults (soft) --- | ||
| grid --> DEFAULT_GRID | ||
| legend --> DEFAULT_LEGEND | ||
| ylabel --> "cdf" | ||
| label --> String(x.name) # single legend entry | ||
|
|
||
| seriescolor --> :auto | ||
|
|
||
| lo_grid = x.lb | ||
| hi_grid = x.ub | ||
|
|
||
| width = hi_grid - lo_grid | ||
|
|
||
| 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) | ||
|
|
||
| x_grid = range(lo_grid, hi_grid, DEFAULT_PLOT_GRID_NUMBER) | ||
|
|
||
| cdf_lo = x_grid .>= x.ub | ||
| cdf_hi = x_grid .> x.lb | ||
|
|
||
| # Plot upper cdf (primary, inherits colour and label) | ||
| @series begin | ||
| seriestype := :path | ||
| alpha --> 1 | ||
| linewidth --> DEFAULT_DISTRIBUTION_WIDTH | ||
| x_grid, cdf_hi | ||
| end | ||
|
|
||
| # Plot lower cdf | ||
| @series begin | ||
| primary := false | ||
| seriestype := :path | ||
| alpha --> 1 | ||
| label := "" | ||
| linewidth --> DEFAULT_DISTRIBUTION_WIDTH | ||
| 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 | ||
| 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}; shade=DEFAULT_FILL_IMPRECISE | ||
| ) where {T<:ProbabilityBox} | ||
| # --- plot-level defaults (soft) --- | ||
| grid --> DEFAULT_GRID | ||
| legend --> DEFAULT_LEGEND | ||
| ylabel --> "cdf" | ||
| 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 | ||
| seriestype := :path | ||
| alpha --> 1 | ||
| linewidth --> DEFAULT_DISTRIBUTION_WIDTH | ||
| x_grid, hi.(cdf_evals) | ||
| end | ||
|
|
||
| # Plot lower cdf | ||
| @series begin | ||
| primary := false | ||
| seriestype := :path | ||
| alpha --> 1 | ||
| linewidth --> DEFAULT_DISTRIBUTION_WIDTH | ||
| label := "" | ||
| x_grid, lo.(cdf_evals) | ||
| end | ||
|
|
||
| # Plot fill | ||
| 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 | ||
|
|
||
| @recipe function _plot(x::Vector{T}) where {T<:UQInput} | ||
| # Filter out Parameter objects | ||
| x_no_params = filter(xi -> !isa(xi, Parameter), x) | ||
|
|
||
| N = length(x_no_params) | ||
| cols = ceil(Int, sqrt(N)) | ||
| rows = ceil(Int, N / cols) | ||
| layout --> (rows, cols) | ||
|
|
||
| # Choose a grid palette once (users can still override via plot(...; palette=...)) | ||
| # palette --> :default # or :default, :Dark2_8, etc. | ||
|
|
||
| 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 | ||
| ### | ||
|
|
||
| # Plot a 2D IntervalBox: | ||
| @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] | ||
|
|
||
| x, y | ||
| 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[] | ||
|
|
||
| # build up coords: # (alternative: use @series) | ||
| 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 | ||
|
|
||
| ### | ||
| # 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you move these
utilincludes down here? It's probably not to important, but I think they can stay at the top.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You defined a
lo(X::Real)andhi(X::Real)function but I don't think you use it anywhere.Do you really need a function for the
.lband.ubof theInterval? To get the bounds of aVector{Interval}you could instead usegetproperty.(X, :lb)andgetproperty.(X, :ub).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review 👍 I think you're right
On the last one, I do find it convenient to have
hiandlofunctions for intervals and reals. It lets you ask for bounds on random sample ofinputs, without knowing which elements are interval or real.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, keep them 👍