I have some functions which each return a constant n number of complex values, and would like to plot one as a series of lines on the complex plane. if I do something like
plot(real.([f.(0.1:.1:5)...;;]'),-imag.([f.(0.1:.1:5)...;;]'))
it technically does give me what I want, but then you lose the vertical axis being labeled as imaginary and the code is also kinda ugly. is there some way I can change the type of the functions or the call to get something more like plot(f, 0.1:.1:5)?
Here are some loose suggestions:
- Add the labels manually
plot(...; xlabel="Re(z)", ylabel="Im(z)") - Just extract the individual vectors of complex numbers and put it as single argument into individual
plot!calls (that will draw the curve in the complex plane with automatic axis labels). - Write a custom plot function that does the above (this is probably what I would go for, since it also avoids calling the function
ftwice. Something like
function plot_complex_vector(f, u; kwargs...)
results = f.(u)
...
plot(...; kwargs...)
end
- Write a plot recipe which is basically a function like the one above, but has a bit more standardized handling of extra kwargs etc. but also more overhead to write.
Wrangling data into larger arrays of the right dimensions in one-liners is always going to look a bit ugly and involve weird tricks like -imag...' for brevity. Sometimes a loop (that does more or less what Sevi suggests) is clearer.
What is the problem when using Plots.jl with:
t = 0.1:0.1:5
plot(f.(t))
# or if you need the conjugate:
plot(conj(f.(t)))
plot doesn’t seem to like that (roots() has same return type as my functions):
julia> using Plots, PolynomialRoots
julia> f(x) = roots([1,2,3,x])
f (generic function with 1 method)
julia> plot(f.(.1:.1:5))
ERROR: MethodError: no method matching isless(::Float64, ::ComplexF64)
The function `isless` exists, but no method is defined for this combination of argument types.
Closest candidates are:
isless(::Missing, ::Any)
@ Base missing.jl:87
isless(::Any, ::Missing)
@ Base missing.jl:88
isless(::AbstractFloat, ::SparseConnectivityTracer.GradientTracer)
@ SparseConnectivityTracer ~/.julia/packages/SparseConnectivityTracer/YYCo5/src/overloads/gradient_tracer.jl:165
...
Stacktrace:
[1] min(x::ComplexF64, y::Float64)
@ Base ./operators.jl:499
[2] expand_extrema!
@ ~/.julia/packages/Plots/uiCPf/src/axes.jl:425 [inlined]
[3] #113
@ ~/.julia/packages/Plots/uiCPf/src/axes.jl:444 [inlined]
[4] foreach
@ ./abstractarray.jl:3187 [inlined]
[5] expand_extrema!(axis::Plots.Axis, v::Vector{ComplexF64})
@ Plots ~/.julia/packages/Plots/uiCPf/src/axes.jl:444
[6] expand_extrema!(sp::Plots.Subplot{Plots.GRBackend}, plotattributes::RecipesPipeline.DefaultsDict)
@ Plots ~/.julia/packages/Plots/uiCPf/src/axes.jl:479
[7] _expand_subplot_extrema(sp::Plots.Subplot{Plots.GRBackend}, plotattributes::RecipesPipeline.DefaultsDict, st::Symbol)
@ Plots ~/.julia/packages/Plots/uiCPf/src/pipeline.jl:433
[8] add_series!(plt::Plots.Plot{Plots.GRBackend}, plotattributes::RecipesPipeline.DefaultsDict)
@ Plots ~/.julia/packages/Plots/uiCPf/src/pipeline.jl:376
[9] _process_seriesrecipe(plt::Any, plotattributes::Any)
@ RecipesPipeline ~/.julia/packages/RecipesPipeline/BGM3l/src/series_recipe.jl:46
[10] _process_seriesrecipes!(plt::Any, kw_list::Any)
@ RecipesPipeline ~/.julia/packages/RecipesPipeline/BGM3l/src/series_recipe.jl:27
[11] recipe_pipeline!(plt::Any, plotattributes::Any, args::Any)
@ RecipesPipeline ~/.julia/packages/RecipesPipeline/BGM3l/src/RecipesPipeline.jl:99
[12] _plot!(plt::Plots.Plot, plotattributes::Any, args::Any)
@ Plots ~/.julia/packages/Plots/uiCPf/src/plot.jl:223
[13] plot(args::Any; kw...)
@ Plots ~/.julia/packages/Plots/uiCPf/src/plot.jl:102
[14] plot(args::Any)
@ Plots ~/.julia/packages/Plots/uiCPf/src/plot.jl:93
[15] top-level scope
@ REPL[3]:1
I’m currently stumbling my way through writing a plot recipe, so should prob mark Sevi’s answer as solution instead of just hearting it; but I’m obviously still open to other solutions if people want to throw them at me
The example doesn’t provide a vector of n-complex numbers, but a vector of vectors of complex numbers.
The following would plot all the roots:
scatter(reduce(vcat, f.(0.1:0.1:5)))
the function itself just returns a vector of complex numbers; the vector of vectorness comes from using the . to distribute through the range
Yeah, of course.