7474"""
7575$(TYPEDSIGNATURES)
7676
77- Return an array of bools to mark solutions in `res` which fall into `classes` but not `not_classes`
77+ Return an array of bools to mark solutions in `res` which fall into `classes` but not `not_classes`.
78+ Only `branches` are considered.
7879"""
79- function _get_mask (res, classes, not_classes= [])
80- classes == " all" && return fill (trues (length (res. solutions[1 ])), size (res. solutions))
81- bools = vcat ([res. classes[c] for c in _vectorise (classes)], [map (.! , res. classes[c]) for c in _vectorise (not_classes)])
82- map (.* , bools... )
80+ function _get_mask (res, classes, not_classes= []; branches= 1 : branch_count (res))
81+ classes == " all" && return fill (trues (length (branches)), size (res. solutions))
82+ bools = vcat ([res. classes[c] for c in _str_to_vec (classes)], [map (.! , res. classes[c]) for c in _str_to_vec (not_classes)])
83+ # m = map( x -> [getindex(x, b) for b in [branches...]], map(.*, bools...))
84+
85+ m = map ( x -> x[[branches... ]], map (.* , bools... ))
8386end
8487
8588
@@ -96,85 +99,62 @@ function _apply_mask(solns::Array{Vector{ComplexF64}}, booleans)
9699end
97100
98101
99- # convert x to Float64, raising a warning if complex
100- function _realify (x, warn= true )
101- ! is_real (x) && ! isnan (x) && warn ? (@warn " Values with non-negligible complex parts have been projected on the real axis!" , x) : nothing
102- real (x)
103- end
102+ """ Project the array `a` into the real axis, warning if its contents are complex. """
103+ function _realify (a:: Array{T} where T <: Number ; warning= " " )
104104
105- function _realify (v:: Vector , warn= true )
106- v_real = Vector {Vector{Float64}} (undef, length (v[1 ]))
107- for branch in eachindex (v_real)
108- values = getindex .(v, branch)
109- values_real = Vector {Float64} (undef, length (values))
110- for (j,x) in pairs (values)
111- if ! is_real (x) && ! isnan (x) && warn
112- (@warn " Values with non-negligible complex parts have been projected on the real axis!" , x)
113- warn = false
114- end
115- values_real[j] = real (x)
105+ warned = false
106+ a_real = similar (a, Float64)
107+ for i in eachindex (a)
108+ if ! isnan (a[i]) && ! warned && ! is_real (a[i])
109+ @warn " Values with non-negligible complex parts have
110+ been projected on the real axis! " * warning
111+ warned = true
116112 end
117- v_real[branch] = values_real
118- end
119- return v_real
120- end
121-
122- function _realify (a:: Matrix , warn= true )
123- a_real = Array {Vector{Vector{Float64}}} (undef, size (a)... )
124- for idx in CartesianIndices (a)
125- v = a[idx]
126- v_real = Vector {Vector{Float64}} (undef, length (v[1 ]))
127- for branch in eachindex (v_real)
128- values = getindex .(v, branch)
129- values_real = Vector {Float64} (undef, length (values))
130- for (j,x) in pairs (values)
131- if ! is_real (x) && ! isnan (x) && warn
132- (@warn " Values with non-negligible complex parts have been projected on the real axis!" , x)
133- warn = false
134- end
135- values_real[j] = real (x)
136- end
137- v_real[branch] = values_real
138- end
139- a_real[idx] = v_real
113+ a_real[i] = real (a[i])
140114 end
141115 return a_real
142116end
143117
144- _vectorise (s:: Vector ) = s
145- _vectorise (s) = [s]
118+
119+ _str_to_vec (s:: Vector ) = s
120+ _str_to_vec (s) = [s]
146121
147122
148123# return true if p already has a label for branch index idx
149124_is_labeled (p:: Plots.Plot , idx:: Int64 ) = in (string (idx), [sub[:label ] for sub in p. series_list])
150125
151126
152- function plot1D (res:: Result ; x:: String = " default" , y:: String , class= " default" , not_class= [], add= false , kwargs... )
127+ function plot1D (res:: Result ; x:: String = " default" , y:: String , class= " default" , not_class= [], branches = 1 : branch_count (res), add= false , kwargs... )
153128
154129 if class == " default"
130+ args = [:x => x, :y => y, :branches => branches]
155131 if not_class == [] # plot stable full, unstable dashed
156- p = plot1D (res; x = x, y = y , class= [" physical" , " stable" ], add= add, kwargs... )
157- plot1D (res; x = x, y = y , class= " physical" , not_class= " stable" , add= true , style= :dash , kwargs... )
132+ p = plot1D (res; args ... , class= [" physical" , " stable" ], add= add, kwargs... )
133+ plot1D (res; args ... , class= " physical" , not_class= " stable" , add= true , style= :dash , kwargs... )
158134 return p
159135 else
160- p = plot1D (res; x = x, y = y , not_class= not_class, class= " physical" , add= add, kwargs... )
136+ p = plot1D (res; args ... , not_class= not_class, class= " physical" , add= add, kwargs... )
161137 return p
162138 end
163139 end
164140
165141 dim (res) != 1 && error (" 1D plots of not-1D datasets are usually a bad idea." )
166142 x = x == " default" ? string (first (keys (res. swept_parameters))) : x
167- X, Y = transform_solutions (res, [x,y]) # first transform, then filter
168- Y = _apply_mask (Y, _get_mask (res, class, not_class))
169- branches = _realify (Y)
143+ X = transform_solutions (res, x, branches= branches)
144+ Y = transform_solutions (res, y, branches= branches)
145+ Y = _apply_mask (Y, _get_mask (res, class, not_class, branches= branches))
146+
147+ # reformat and project onto real, warning if needed
148+ branch_data = [_realify ( getindex .(Y, i), warning= " branch " * string (k) ) for (i,k) in enumerate (branches)]
170149
171150 # start a new plot if needed
172151 p = add ? Plots. plot! () : Plots. plot ()
173152
174153 # colouring is matched to branch index - matched across plots
175- for k in findall (x -> ! all (isnan .(x)), branches[1 : end ]) # skip NaN branches but keep indices
176- l = _is_labeled (p, k) ? nothing : k
177- Plots. plot! (_realify .(getindex .(X, k)), branches[k]; color= k, label= l, xlabel= latexify (x), ylabel= latexify (y), kwargs... )
154+ for k in findall (x -> ! all (isnan .(x)), branch_data) # skip NaN branch_data
155+ global_index = branches[k]
156+ lab = _is_labeled (p, global_index) ? nothing : global_index
157+ Plots. plot! (_realify (getindex .(X, k)), branch_data[k]; color= k, label= lab, xlabel= latexify (x), ylabel= latexify (y), kwargs... )
178158 end
179159
180160 return p
@@ -185,8 +165,7 @@ plot1D(res::Result, y::String; kwargs...) = plot1D(res; y=y, kwargs...)
185165
186166function plot2D (res:: Result ; z:: String , branch:: Int64 , class= " physical" , not_class= [], add= false , kwargs... )
187167 X, Y = values (res. swept_parameters)
188- Z = getindex .(_apply_mask (transform_solutions (res, z), _get_mask (res, class, not_class)), branch) # first transform, then filter
189-
168+ Z = getindex .(_apply_mask (transform_solutions (res, z, branches= branch), _get_mask (res, class, not_class, branches= branch)), 1 ) # there is only one branch
190169 p = add ? Plots. plot! () : Plots. plot () # start a new plot if needed
191170
192171 ylab, xlab = latexify .(string .(keys (res. swept_parameters)))
@@ -219,15 +198,17 @@ function plot2D_cut(res::Result; y::String, cut::Pair, class="default", not_clas
219198
220199 X = res. swept_parameters[x]
221200 Y = _apply_mask (transform_solutions (res, y), _get_mask (res, class, not_class)) # first transform, then filter
222- branches = _realify (x_index== 1 ? Y[:, cut_par_index] : Y[cut_par_index, :])
201+ branches = x_index== 1 ? Y[:, cut_par_index] : Y[cut_par_index, :]
202+
203+ branch_data = [_realify ( getindex .(branches, i), warning= " branch " * string (k) ) for (i,k) in enumerate (1 : branch_count (res))]
223204
224205 # start a new plot if needed
225206 p = add ? Plots. plot! () : Plots. plot ()
226207
227208 # colouring is matched to branch index - matched across plots
228- for k in findall (branch -> ! all (isnan .(branch)), branches[ 1 : end ] ) # skip NaN branches but keep indices
209+ for k in findall (branch -> ! all (isnan .(branch)), branch_data ) # skip NaN branches but keep indices
229210 l = _is_labeled (p, k) ? nothing : k
230- Plots. plot! (X, branches[k] ; color= k, label= l, xlabel= latexify (string (x)), ylabel= latexify (y), kwargs... )
211+ Plots. plot! (X, _realify ( getindex .( branches, k)) ; color= k, label= l, xlabel= latexify (string (x)), ylabel= latexify (y), kwargs... )
231212 end
232213
233214 return p
@@ -302,6 +283,9 @@ Class selection done by passing `String` or `Vector{String}` as kwarg:
302283Other kwargs are passed onto Plots.gr()
303284"""
304285function plot_spaghetti (res:: Result ; x:: String , y:: String , z:: String , class= " default" , not_class= [], add= false , kwargs... ):: Plots.Plot
286+ if dim (res) == 2
287+ error (" Data dimension " , dim (res), " not supported" )
288+ end
305289
306290 if class == " default"
307291 if not_class == [] # plot stable full, unstable dashed
@@ -325,16 +309,18 @@ function plot_spaghetti(res::Result; x::String, y::String, z::String, class="def
325309 isnothing (z_index) && error (" The variable $z was not swept over." )
326310
327311 Z = res. swept_parameters. vals[z_index]
328- X = _apply_mask (transform_solutions (res, x), _get_mask (res, class, not_class)) |> _realify
329- Y = _apply_mask (transform_solutions (res, y), _get_mask (res, class, not_class)) |> _realify
312+ X = _apply_mask (transform_solutions (res, x), _get_mask (res, class, not_class))
313+ Y = _apply_mask (transform_solutions (res, y), _get_mask (res, class, not_class))
330314
331315 # start a new plot if needed
332316 p = add ? Plots. plot! () : Plots. plot ()
333317
318+ branch_data = [_realify ( getindex .(X, i), warning= " branch " * string (k) ) for (i,k) in enumerate (1 : branch_count (res))]
319+
334320 # colouring is matched to branch index - matched across plots
335- for k in findall (x -> ! all (isnan .(x)), X[ 1 : end ] ) # skip NaN branches but keep indices
321+ for k in findall (x -> ! all (isnan .(x)), branch_data ) # skip NaN branches but keep indices
336322 l = _is_labeled (p, k) ? nothing : k
337- Plots. plot! (X[k], Y[k] , Z; _set_Plots_default... ,
323+ Plots. plot! (_realify ( getindex .(X, k)), _realify ( getindex .(Y, k)) , Z; _set_Plots_default... ,
338324 color= k, label= l, xlabel= latexify (x), ylabel= latexify (y), zlabel= latexify (z), xlim= :symmetric , ylim= :symmetric , kwargs... )
339325 end
340326 return p
0 commit comments