Hi guys Im trying to plot my graph but it keep on increasing the number of line plotted each time. Plot{Plots.GRBackend() n=5} I want only n=2. How do I delete the unnecessary lines.
Do you have a code snippet that you’re using to generate this?
Here is the code I’m currently using
function f(x; θ=15*pi/180)
if (x>-R1*sin(θ)) && (x<R1*sin(θ))
(R_throat+R1*(1-cos(asin(x/R1))))
elseif (x>-R1*sind(θ))
(m*x+Y0)
end
end
using Plots
x=range(0, Xe, length=100)
y=m .* x .+Y0
plot((x,f.(x, θ=15*pi/180)), ylims=(0,0.75), color="blue")
plot!((-x,f.(x, θ=15*pi/180)), ylims=(0,0.75), color="blue")
I’m not sure of your experience level with the language, so pardon if some are pedantic, but I’ve got a couple of notes here that I hope might be helpful.
Your function f
has inconsistent usage of sin
vs sind
; I think under the elseif
condition you intended to use sin(θ)
. Also, the if
/elseif
conditions you provided can be cleaned up a bit. What happens if x == R1*sin(θ)
? See the code block at the bottom of this post for a suggestion.
You’re referencing a few global variables that aren’t provided, and I can’t replicate your current result as-is. Specifically, R1
, R_throat
, m
, Y0
, and Xe
aren’t defined here. In some cases, like in the REPL, Julia will run this function without issue; but in others like executing a source file directly you can get errors/warnings when trying to access globally-scoped variables from within a function without explicitly declaring them as global. Referencing globals from within a function has some drawbacks, especially in terms of performance, but sometimes it’s what you want to do.
You define a function f(x; θ=15*pi/180)
which has a keyword argument θ with a default value 15pi/180
. This means that any time you call simply f(x)
, it will by default have defined a variable θ = 15pi/180
inside. So, in your plot calls at the bottom there’s no real need to call f.(x, θ=15*pi/180))
since that’s already the default value; you could also just have written f.(x)
here.
The Plots.jl package always felt slightly cryptic to me, so I’m not sure if putting your data in a tuple, i.e. (x, y)
has any special meaning, but the syntax plot(x, y)
where x
and y
are equal-length vectors of corresponding point values works just fine.
Keyword argument settings passed to plot
are usually respected when the figure is modified by a plot!
call, so no need to repeat the ylims
settings. In fact, you can also make a plot!
call with nothing but keyword arguments if you’d like to group those settings all at once.
using Plots
# Values of these globals not provided, so I'm just guessing for each
m = 0.2
R1 = 5.0
R_throat = 0.25
Xe = pi/2
Y0 = 0.25
function f(x; θ=15pi/180)
# These names reference global-scope variables (defined above)
global Y0, R1, R_throat, m
if -R1*sin(θ) < x < R1*sin(θ)
return R_throat + R1 * (1 - cos(asin(x/R1)))
else
return m * x + Y0
end
end
# Plot f over a range of x's
xs = range(0, Xe, length=100)
plot(xs, f.(xs), color=:blue)
plot!(-xs, f.(xs), color=:red)
plot!(ylims=(0,0.75), legend=:bottomright)
Or, alternately, the plot could be constructed as:
xs = range(-Xe, Xe, length=100)
plot(xs, f.(abs.(xs)), color=:blue)
plot!(ylims=(0,0.75), legend=:bottomright)
Thank you very much I like your method and its much more nicer, now I gotta do the same thing as I did before but mirror it to the y axis been trying to do this method for a few days now . And its kinda weird but your method does not occur the problem that I had faced before which is this what does legend=: bottomright do if I may ask?
using Plots
function f(x; θ=15pi/180)
global Y0, R1, R_throat, m
if -R1*sin(θ) < x < R1*sin(θ)
return R_throat + R1 * (1 - cos(asin(x/R1)))
else
return m * x + Y0
end
end
x = range(0, Xe, length=100)
plot(x, f.(x), color=:blue)
plot!(x, -f.(x), color=:blue)
plot!(ylims=(-0.75,0.75), legend=:bottomright)
title!("Rocket Nozzle")
xlabel!("m")
ylabel!("Radius(m)")
Plots.jl has a keyword setting for subplots legend_position
, which can be set using the shorter alias legend
, that requests it place the plot legend (the box with the line labels y1
and y2
in your example) in a specific location. Without the setting, Plots will just select what it thinks is a suitable location, but sometimes it’s nice to put it where you want it instead.
You can also control the labels used to describe the lines in the legend by adding a label
keyword when the particular line is plotted.
plot(x, f.(x), color=:blue, label="The top line")
plot!(x, -f.(x), color=:blue, label="The bottom line")
Alternatively, label=missing
indicates that you don’t want that particular line to be labeled in a legend.
I suspect that getting five lines plotted was fallout from the bug you had with sin
vs sind
and the way the conditions were defined. If the original if
and elseif
conditions weren’t hit for a particular x
value, then the function would return nothing
. In some cases you can use values like nothing
to break a single line in Plots.jl into multiple.