How to delete the number of lines plotted in the graph

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?

Ref: Please read: make it easier to help you

1 Like

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)

image

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)

image

2 Likes

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 :heart_eyes:. 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.

1 Like

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.

1 Like