How to Transform Plots / Shape with Plots.jl

Hi all,

I want to transform the shape that I plot with this code:

using Plots, LaTeXStrings, Roots, SymPy
gr()


f(x) = sin(x^2) + cos(2x) - 6
g(x) = sin(x^2) + cos(2x) 

plot(f,2,4, ylims=(-8,3), 
	legend=:topleft, linecolor=:green, label="")
plot!(g,2,4, ylims=(-8,3),
	legend=:topleft, linecolor=:green, label="")

plot!([2,2],[f(2),g(2)], label="", linecolor=:green)
plot!([4,4],[f(4),g(4)], label="", linecolor=:green)

so it can be mirrored, the transformation will be translation and mirroring. Any package here that can help me?

This is the my plot:
Capture d’écran_2022-12-24_14-59-00

This is what I want to achieve, the mirror of the above shape:

Capture d’écran_2022-12-24_14-59-46

Cavalieri’s Principle

Have you tried declaring your own types to scale and shift the function?

julia> struct YShift{F, Y} <: Function f::F; y::Y end

julia> (g::YShift)(x) = g.f(x) + g.y

julia> struct YScale{F, S} <: Function f::F; s::S end

julia> (g::YScale)(x) = g.s * g.f(x)

julia> plot!(YShift(f, -6), 2, 4, linecolor=:green)

julia> plot!(YScale(f, -1), 2, 4, linecolor=:green)
3 Likes

Defining new types may be a bit of an overkill for this problem if it does not repeat a few times. Here is another function with some ‘functional’ approach:

function make_fg_plot()
    f(x) = sin(x^2) + cos(2x) - 6
    g(x) = sin(x^2) + cos(2x)

    yshift = y -> y + 5
    yreflection = y -> -y
    ytransform = yshift ∘ yreflection

    plt = plot(; ylims = (-8, 15), legend = :topleft)
    for (T, attrs) in [(identity, (;label = "", linecolor = :green)), 
                       (ytransform, (;label = "", linecolor = :red))]
        plot!(plt, T ∘ f, 2, 4; attrs...)
        plot!(plt, T ∘ g, 2, 4; attrs...)

        plot!(plt, [2, 2], T.([f(2), g(2)]); attrs...)
        plot!(plt, [4, 4], T.([f(4), g(4)]); attrs...)
    end
    return plt
end

This function returns the plt object and may be called from REPL or displayed otherwise.

3 Likes

It is colorful,

I thought someone here can point me to a package that can transform plot of curves, but we need to create our own function instead. Thanks!

Capture d’écran_2022-12-25_11-43-44

Where or how did you learn to make the function? I want to learn and understand more.

Why write

for (T, attrs) 

and

plot!(plt, T ∘ f, 2, 4; attrs...)

So identity is defined already in Julia?

I add another simple function for anyone who wants to learn:

using Plots, LaTeXStrings, Roots, SymPy
gr()

function make_fg_plot()
    f(x) = sin(x^2) + cos(2x) - 6
    g(x) = sin(x^2) + cos(2x)

    yshift = y -> y + 5
    yreflection = y -> -y
    ytransform = yshift ∘ yreflection

    plt = plot(; ylims = (-8, 15), legend = :topleft)
    for (T, attrs) in [(identity, (;label = "", linecolor = :green)), 
                       (ytransform, (;label = "", linecolor = :red))]
        plot!(plt, T ∘ f, 2, 4; label="")
        plot!(plt, T ∘ g, 2, 4; label="")

	for i=0:0.2:2        
	plot!(plt, [2+i, 2+i], T.([f(2+i), g(2+i)]); label="")
	end
    end
    return plt
end

make_fg_plot()
1 Like

I like this approach. It’s not even really specific to the y-axis, and using built-in partial application types makes it play nice with things like InverseFunctions.jl:

shift(ν) = Base.Fix1(+, ν)
shift(5) ∘ f # y-up-shift
f ∘ shift(2) # x-left-shift
2 Likes

When I ran the function, it didn’t have all the colors (because of the attr... bit). So there is an odd discrepancy. Maybe it’s a version issue. Weird.