Multiple Plots for Parametric Equations

Hi all,

I want to do multiple plots with layout for parametric equations. This is my code:

using Plots, LaTeXStrings
pyplot()

θ1 = 0:0.1:2π
x1 = 3 .*cos.(θ1)
y1 = 3 .*sin.(θ1)

x2 = 3 .*cos.(θ1)
y2 = sin.(θ1)

θ2 = 0:0.1:6π
x3 = θ2.*cos.(θ2)
y3 = θ2.*sin.(θ2)

x4 = cos.(θ1)
y4 = sin.(2θ1)

p1 = (x1, y1, -10,10)
p2 = (x2, y2, -10,10)
p3 = (x3, y3, -10,10)
p4 = (x4, y4, -10,10)

s1 = L"(x,y) = (3 \ \cos \ t, 3 \ \sin \ t)";
s2 = L"(x,y) = (3 \ \cos \ t, \sin \ t)";
s3 = L"(x,y) = (t \ \cos \ t, t \ \sin \ t)";
s4 = L"(x,y) = (\cos \ t, \sin \ 2t)";

plot(p1, p2, p3, p4, layout = (2, 2), xaxis = "x", yaxis = "y", label=[s1 s2 s3 s4], 
title=["a" "b" "c" "d"],
titleloc = :bottom, titlefont = font(8))

but there is an error:

LoadError: Couldn't process recipe args: (Vector{Float64}, Vector{Float64}, Vector{Float64}, Vector{Float64})
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:33
  [2] macro expansion
    @ ~/.julia/packages/RecipesPipeline/XxUHt/src/user_recipe.jl:158 [inlined]
  [3] apply_recipe(::AbstractDict{Symbol, Any}, ::Any, ::Any, ::Any, ::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesBase/eU0hg/src/RecipesBase.jl:300
  [4] _process_userrecipes!(plt::Any, plotattributes::Any, args::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/XxUHt/src/user_recipe.jl:38
  [5] recipe_pipeline!(plt::Any, plotattributes::Any, args::Any)
    @ RecipesPipeline ~/.julia/packages/RecipesPipeline/XxUHt/src/RecipesPipeline.jl:72
  [6] _plot!(plt::Plots.Plot, plotattributes::Any, args::Any)
    @ Plots ~/.julia/packages/Plots/M4dfL/src/plot.jl:223
  [7] plot(::Any, ::Vararg{Any}; kw::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}})
    @ Plots ~/.julia/packages/Plots/M4dfL/src/plot.jl:102
  [8] top-level scope
    @ ~/LasthrimProjection/Test/plotjulia.jl:28
  [9] include(fname::String)
    @ Base.MainInclude ./client.jl:451
 [10] top-level scope
    @ REPL[1]:1
in expression starting at /home/browni/LasthrimProjection/Test/plotjulia.jl:28

For plotting multiple plots you should pass figures to plot, i.e.

p1 = plot(rand(5))
p2 = plot(rand(5))
plot(p1, p2)

In your example, p1, p2, etc are just tuples:

julia> θ1 = 0:0.1:2π;

julia> θ1 = 0:0.1:2π;

julia> y1 = 3 .*sin.(θ1);

julia> x1 = 3 .*cos.(θ1);

julia> p1 = (x1, y1, -10,10)
([3.0, 2.9850124958340776, 2.940199733523725, 2.866009467376818, 2.7631829820086553, 2.6327476856711183, 2.4760068447290347, 2.2945265618534654, 2.0901201280414963, 1.8648299048119932  …  1.6631230085374846, 1.904078627827904, 2.12600932287378, 2.3266976355307505, 2.5041383545174796, 2.656558550823958, 2.782435292232108, 2.880510859951098, 2.949805315327754, 2.9896262910696523], [0.0, 0.29950024994048446, 0.5960079923851836, 0.8865606199840188, 1.1682550269259515, 1.438276615812609, 1.6939274201851064, 1.9326530617130735, 2.1520682726985685, 2.3499807288824504  …  -2.4968023266717023, -2.3182934626679614, -2.1166209767111757, -1.8937999136169625, -1.6520566277929127, -1.3938065382412699, -1.121629994490708, -0.8382464945967776, -0.546487512816285, -0.2492682084524892], -10, 10)

You probably want to create actual plots in those lines?

Yes I want to plot it like this, but with layout 2 x 2:

Capture d’écran_2023-01-18_15-58-57

I am able to do parametric plot (single plot), here is the code:

using Plots, LaTeXStrings; gr()

# To plot a spiral centered at (0, 0) 
θ = 0:0.1:10.1π
x = θ.*cos.(θ)
y = θ.*sin.(θ)
plot(x, y, xlims=(-50,50), ylims=(-50,50),
	label=L"(x,y) = (t \ \cos \ t , t \ \sin \ t)",
	framestyle=:zerolines, aspect_ratio=:equal)


How to make multiple plots for parametric equations? What do I need to do to fix p1,p2,p3,p4 ?

Yes that’s what I thought and that’s my point above - p1 needs to be the actual plot you want to have in the [1, 1] position.

So you need:

p1 = plot(x, y, xlims=(-50,50), ylims=(-50,50),
	label=L"(x,y) = (t \ \cos \ t , t \ \sin \ t)",
	framestyle=:zerolines, aspect_ratio=:equal)

then something equivalent for p2 etc and then you do

plot(p1, p2, p3, p4, layout = (2, 2))
1 Like

This works:

using Plots, LaTeXStrings
pyplot()

θ1 = 0:0.1:2π
x1 = 3 .*cos.(θ1)
y1 = 3 .*sin.(θ1)

x2 = 3 .*cos.(θ1)
y2 = sin.(θ1)

θ2 = 0:0.1:6π
x3 = θ2.*cos.(θ2)
y3 = θ2.*sin.(θ2)

x4 = cos.(θ1)
y4 = sin.(2θ1)

p1 = plot(x1, y1, xlims=(-50,50), ylims=(-50,50),
	framestyle=:zerolines)
p2 = plot(x2, y2, xlims=(-50,50), ylims=(-50,50),
	framestyle=:zerolines)
p3 = plot(x3, y3, xlims=(-50,50), ylims=(-50,50),
	framestyle=:zerolines)
p4 = plot(x4, y4, xlims=(-50,50), ylims=(-50,50),
	framestyle=:zerolines)

s1 = L"(x,y) = (3 \ \cos \ t, 3 \ \sin \ t)";
s2 = L"(x,y) = (3 \ \cos \ t, \sin \ t)";
s3 = L"(x,y) = (t \ \cos \ t, t \ \sin \ t)";
s4 = L"(x,y) = (\cos \ t, \sin \ 2t)";

plot(p1, p2, p3, p4, layout = (2, 2), xaxis = "x", yaxis = "y", label=[s1 s2 s3 s4], 
title=["a" "b" "c" "d"],
titleloc = :bottom, titlefont = font(8))

but it is so weird, I think p1 = (x1, y1, -10,10) is enough to plot… or I just lack of experience…

This suggests that you have some deep misunderstanding about how Julia works which would probably be useful to address to make your future coding easier. Have you considered reading the Julia manual to get a better understanding of how the language works at the most basic level (e.g. what is a function call, what is a variable, what are the basic data structures etc)?

The section on tuples is here:

https://docs.julialang.org/en/v1/manual/functions/#Tuples

But the wider function section of the manual is probably relevant for you. The key here is that parentheses () are used for different things in Julia, in the main:

  • Grouping statements to change the order of evaluation:
julia> 1 == 2 | 3 == 3
false

julia> (1 == 2) | (3 == 3)
true

This is similar to what you do in maths notation, 2 + 3 \times 4 \neq (2 + 3) \times 4

  • Constructing tuples (see the link above)
julia> typeof((1, 2))
Tuple{Int64, Int64}

julia> typeof((1, ))
Tuple{Int64}
  • Calling functions:
julia> f(x, y) = 2x + 3y
f (generic function with 2 methods)

julia> f(1, 2)
8

Now the key here is that to call a function, the parens need to directly follow the identifier of the function:

julia> f (1, 2)
ERROR: syntax: space before "(" not allowed in "f (" at REPL[20]:1

That’s because - as we’ve seen in the second bullet point above - just writing (1, 2) just creates a tuple with the elements 1 and 2.

So when you say

you are conflating the function call with the tuple syntax. There is no way for Julia to know that when you write

(x1, y1, -10, 10)

you actually meant

plot(x1, y1, -10, 10)

because (x1, y1, -10, 10) is perfectly valid syntax which means “please create a tuple with four elements, the first element being the vector x1, the second element being the vector y1, the third element being -10 and the fourth element being 10”.

I hope that thinking about why (x1, y1, -10, 10) cannot be the same as plot(x1, y1, -10, 10) will help you get a better understanding of how the language works - if somehow it isn’t clear do ask further questions.

2 Likes

Yes I misunderstand it, because I am trying to make it work fast, guess I should have be more slower and read the Julia’ manual more.