Skip to content

Commit 6bfa41d

Browse files
committed
ribbon plots introduce sample trajectories
1 parent f490983 commit 6bfa41d

File tree

2 files changed

+119
-38
lines changed

2 files changed

+119
-38
lines changed

src/plotting.jl

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ handle_args(p) = handle_args(p.args...)
1414
handle_args(args...) = throw(ArgumentError("The plot function should be called with the signature plotfun([x=1:length(y)], y::Vector{Particles}, [q=0.025])"))
1515

1616
function quantiles(y,q::Number)
17-
m = mean.(y)
17+
m = vec(mean.(y))
1818
q > 0.5 && (q = 1-q)
19-
lower = -(quantile.(y,q)-m)
20-
upper = quantile.(y,1-q)-m
19+
lower = reshape(-(quantile.(vec(y),q)-m), size(y))
20+
upper = reshape(quantile.(vec(y),1-q)-m, size(y))
2121
lower,upper
2222
end
2323

2424
function quantiles(y,q)
25-
m = mean.(y)
26-
lower = -(quantile.(y,q[1])-m)
27-
upper = quantile.(y,q[2])-m
25+
m = vec(mean.(y))
26+
lower = reshape(-(quantile.(vec(y),q[1])-m), size(y))
27+
upper = reshape(quantile.(vec(y),q[2])-m, size(y))
2828
lower,upper
2929
end
3030

@@ -55,6 +55,8 @@ function to1series(x,y)
5555
x2,y2
5656
end
5757

58+
to1series(y) = to1series(1:size(y,1),y)
59+
5860
@userplot MCplot
5961
@recipe function plt(p::MCplot)
6062
x,y,q = handle_args(p)
@@ -75,12 +77,39 @@ end
7577
end
7678

7779
@userplot Ribbonplot
78-
@recipe function plt(p::Ribbonplot)
80+
@recipe function plt(p::Ribbonplot; N=false)
7981
x,y,q = handle_args(p)
80-
label --> "Mean with $q quantile"
81-
m = mean.(y)
82-
ribbon := quantiles(y, q)
83-
x,m
82+
if N > 0
83+
for col = 1:size(y,2)
84+
yc = y[:,col]
85+
m = mean.(yc)
86+
@series begin
87+
label --> "Mean with $q quantile"
88+
ribbon := quantiles(yc, q)
89+
x,m
90+
end
91+
@series begin
92+
ribbon := quantiles(yc, q)
93+
m
94+
end
95+
@series begin
96+
M = Matrix(yc)
97+
np,ny = size(M)
98+
primary := false
99+
nc = N > 1 ? N : min(np, 50)
100+
seriesalpha --> max(1/sqrt(nc), 0.1)
101+
chosen = randperm(np)[1:nc]
102+
to1series(M[chosen, :]')
103+
end
104+
end
105+
else
106+
@series begin
107+
label --> "Mean with $q quantile"
108+
m = mean.(y)
109+
ribbon := quantiles(y, q)
110+
x,m
111+
end
112+
end
84113
end
85114

86115
"""
@@ -99,31 +128,49 @@ Plots all trajectories represented by a vector of particles. `N > 1` controls th
99128
mcplot
100129

101130
"""
102-
ribbonplot(x,y,[q=0.025])
131+
ribbonplot(x,y,[q=0.025]; N=true)
103132
104133
Plots a vector of particles with a ribbon covering quantiles `q, 1-q`.
105134
If `q::Tuple`, then you can specify both lower and upper quantile, e.g., `(0.01, 0.99)`.
135+
136+
If a positive number `N` is provided, `N` sample trajectories will be plotted on top of the ribbon.
106137
"""
107138
ribbonplot
108139

109140

110141

111-
@recipe function plt(y::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, q=0.025)
142+
@recipe function plt(y::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, q=0.025; N=true)
112143
label --> "Mean with ($q, $(1-q)) quantiles"
113-
ribbon := quantiles(y, q)
114-
mean.(y)
144+
if N > 0
145+
for col = 1:size(y,2)
146+
yc = y[:,col]
147+
@series begin
148+
ribbon := quantiles(yc, q)
149+
mean.(yc)
150+
end
151+
@series begin
152+
M = Matrix(yc)
153+
np,ny = size(M)
154+
primary := false
155+
nc = N > 1 ? N : min(np, 50)
156+
seriesalpha --> max(1/sqrt(nc), 0.1)
157+
chosen = randperm(np)[1:nc]
158+
M[chosen, :]'
159+
end
160+
end
161+
end
115162
end
116163

117164

118-
@recipe function plt(func::Function, x::MvParticles, q=0.025)
165+
@recipe function plt(func::Function, x::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, q=0.025)
119166
y = func.(x)
120167
label --> "Mean with ($q, $(1-q)) quantiles"
121168
xerror := quantiles(x, q)
122169
yerror := quantiles(y, q)
123170
mean.(x), mean.(y)
124171
end
125172

126-
@recipe function plt(x::MvParticles, y::MvParticles, q=0.025; points=false)
173+
@recipe function plt(x::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, y::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, q=0.025; points=false)
127174
my = mean.(y)
128175
mx = mean.(x)
129176
if points
@@ -133,23 +180,50 @@ end
133180
seriesalpha --> 0.1
134181
Matrix(x), Matrix(y)
135182
end
183+
@series begin
184+
mx, my
185+
end
136186
else
137-
yerror := quantiles(y, q)
138-
xerror := quantiles(x, q)
139-
label --> "Mean with $q quantile"
187+
@series begin
188+
yerror := quantiles(y, q)
189+
xerror := quantiles(x, q)
190+
label --> "Mean with $q quantile"
191+
mx, my
192+
end
140193
end
141-
mx, my
142194
end
143195

144-
@recipe function plt(x::MvParticles, y::AbstractArray, q=0.025)
196+
@recipe function plt(x::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, y::AbstractArray, q=0.025)
145197
mx = mean.(x)
146198
lower,upper = quantiles(x, q)
147199
xerror := (lower,upper)
148200
mx, y
149201
end
150202

151-
@recipe function plt(x::AbstractArray, y::MvParticles, q=0.025)
152-
ribbon := quantiles(y, q)
153-
label --> "Mean with ($q, $(1-q)) quantiles"
154-
x, mean.(y)
203+
@recipe function plt(x::AbstractArray, y::Union{MvParticles,AbstractMatrix{<:AbstractParticles}}, q=0.025; N=true)
204+
if N > 0
205+
for col = 1:size(y,2)
206+
yc = y[:,col]
207+
@series begin
208+
ribbon := quantiles(yc, q)
209+
label --> "Mean with ($q, $(1-q)) quantiles"
210+
x, mean.(yc)
211+
end
212+
@series begin
213+
M = Matrix(yc)
214+
np,ny = size(M)
215+
primary := false
216+
nc = N > 1 ? N : min(np, 50)
217+
seriesalpha --> max(1/sqrt(nc), 0.1)
218+
chosen = randperm(np)[1:nc]
219+
to1series(x, M[chosen, :]')
220+
end
221+
end
222+
else
223+
@series begin
224+
ribbon := quantiles(y, q)
225+
label --> "Mean with ($q, $(1-q)) quantiles"
226+
x, mean.(y)
227+
end
228+
end
155229
end

test/runtests.jl

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -561,22 +561,28 @@ Random.seed!(0)
561561
@time @testset "plotting" begin
562562
@info "Testing plotting"
563563
p = Particles(100)
564-
v = [p,p]
564+
v = randn(3) .+ Particles.(10)
565+
M = randn(3,2) .+ Particles.(10)
565566
@test_nowarn Plots.plot(p)
566567
@test_nowarn Plots.plot(v)
568+
@test_nowarn Plots.plot(v, N=8)
569+
@test_nowarn Plots.plot(M, N=10)
567570
@test_nowarn Plots.plot(x->x^2,v)
568571
@test_nowarn Plots.plot(v,v)
572+
@test_nowarn Plots.plot(v,v, N=10)
569573
@test_nowarn Plots.plot(v,v; points=true)
570-
@test_nowarn Plots.plot(v,ones(2))
571-
@test_nowarn Plots.plot(1:2,v)
572-
573-
@test_nowarn errorbarplot(1:2,v)
574-
@test_nowarn errorbarplot(1:2,[v v])
575-
@test_nowarn mcplot(1:2,v)
576-
@test_nowarn mcplot(1:2,v, 10)
577-
@test_nowarn mcplot(1:2,[v v])
578-
@test_nowarn ribbonplot(1:2,v)
579-
@test_nowarn ribbonplot(1:2,v,(0.1,0.9))
574+
@test_nowarn Plots.plot(v,ones(3))
575+
@test_nowarn Plots.plot(1:3,v)
576+
@test_nowarn Plots.plot(1:3, v, N=10)
577+
@test_nowarn Plots.plot(1:3, M, N=10)
578+
579+
@test_nowarn errorbarplot(1:3,v)
580+
@test_nowarn errorbarplot(1:3,[v v])
581+
@test_nowarn mcplot(1:3,v)
582+
@test_nowarn mcplot(1:3,v, 10)
583+
@test_nowarn mcplot(1:3,[v v])
584+
@test_nowarn ribbonplot(1:3,v)
585+
@test_nowarn ribbonplot(1:3,v,(0.1,0.9))
580586

581587
@test_nowarn errorbarplot(v)
582588
@test_nowarn errorbarplot([v v])
@@ -585,13 +591,14 @@ Random.seed!(0)
585591
@test_nowarn mcplot([v v])
586592
@test_nowarn ribbonplot(v)
587593
@test_nowarn ribbonplot(v,(0.1,0.9))
594+
@test_nowarn ribbonplot(v, N = 2)
588595

589596
@test_nowarn errorbarplot(v, 0.1)
590597
@test_nowarn errorbarplot([v v], 0.1)
591598
@test_nowarn mcplot(v, 0.1)
592599
@test_nowarn ribbonplot(v, 0.1)
593600

594-
@test_throws ArgumentError errorbarplot(1:2, (1:2) 0.1, 1,1)
601+
@test_throws ArgumentError errorbarplot(1:3, (1:3) 0.1, 1,1)
595602

596603
@test_nowarn MonteCarloMeasurements.print_functions_to_extend()
597604
end

0 commit comments

Comments
 (0)