# Need Help to Create Animation for Tangent Line with Luxor

**URL:** https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809
**Category:** General Usage
**Tags:** package
**Created:** [September 26, 2022, 12:34pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809 "2022-09-26T12:34:24Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [September 26, 2022, 12:34pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/1 "2022-09-26T12:34:25Z")

</div>

Hi all,

I want to understand more of tangent line / gradient line then read the wikipedia and saw the animation here for the tangent line:

> **[Tangent](https://en.wikipedia.org/wiki/Tangent)**
>
> In geometry, the tangent line (or simply tangent) to a plane curve at a given point is, intuitively, the straight line that "just touches" the curve at that point. Leibniz defined it as the line through a pair of infinitely close points on the curve. More precisely, a straight line is tangent to the curve y = f(x) at a point x = c if the line passes through the point (c, f(c)) on the curve and has slope f'(c), where f' is the derivative of f. A similar definition applies to space curves and cu

I create the plot (static image):

```julia
using Plots, LaTeXStrings
gr()

f(x) = -x^2 + 2x + 2
f'

# gradient_line(f, x₀) is a tangent line with an intercept at point x₀ 
# in other words it will pass x₀ 
# and a slope of f'(x₀) - essentially your usual y = a + bx 
# where a is the value of the actual function at the point x₀ through 
# which we want the line to pass, 
# b is the derivative of the function at that point, 
# and the "x" in y=a+bx is replaced by x-x₀ 
# because our "origin" is the point at which we're taking the tangent. 

gradient_line(f, x₀) = (x -> f(x₀) + f'(x₀)*(x-x₀))

default(markerstrokecolor = "white", linewidth = 2);

#Plot f
plot(f, -3:0.1:5, label = "f(x) = -x² + 2x + 2", xlabel = "x", ylabel = "f(x)");

# Plot tangent lines
scatter!([-1], [f(-1)], label = "", markersize = 5);
plot!(gradient_line(f, -1), -3:0.1:0.5, label = "f'(-1)", color = 2);

scatter!([1/2], [f(1/2)], label = "", markersize = 5, color = 3);
plot!(gradient_line(f, 1/2), -1:0.1:2, label = "f'(1/2)", color = 3)

scatter!([2], [f(2)], label = "", markersize = 5, color = 4);
plot!(gradient_line(f, 2), 0.2:0.1:3, label = "f'(2)", color = 4)

scatter!([3], [f(3)], label = "", markersize = 5, color = 5);
plot!(gradient_line(f, 3), 0.8:0.1:4, label = "f'(3)", color = 5)

```

Now, I want to create the moving tangent lines animation, but there is an error, which I have no idea why it said missing comma or ), it works at the above codes…

```julia
using Plots, LaTeXStrings
using Luxor
gr()

let
    f(x) = x*(sin(x^(2))+1
    f'
    gradient_line(f, x₀) = (x -> f(x₀) + f'(x₀)*(x-x₀))
    default(markerstrokecolor = "white", linewidth = 2);
    w, h = 600, 400
    i = 1
    
    plot(f, -3:0.1:5, label = L"f(x) = x \ * sin(x^{2}) + 1", 
	 xlabel = "x", ylabel = "f(x)");

    function frame(scene, i)
        
        background("white"); sethue("green")

        # translate near bottom right corner
        # scatter([i], [f(i)], label = "", markersize = 5);
        plot(gradient_line(f, i), -3:0.1:0.5, label = "", color = 2);
        circle_marker_pos = getworldposition(Point([i], f[i]))
	
	for k = 1:0.1:3
		setfont("Georgia Bold", 73)
		sethue("black")
		text(string("x = $k"),
		Point(O.x-83, O.y-108),
		halign=:center)
	end

        i += 0.1

    end
    demo = Movie(600, 400, "needforspeedtangent")
    animate(demo, [Scene(demo, frame, 1:360)], creategif=true)
end

```

**LoadError: syntax: missing comma or ) in argument list**  
**Stacktrace:**  
\*\* [1] top-level scope\*\*  
\*\* @ ~/LasthrimProjection/plot.jl:7\*\*  
\*\* [2] include(fname::String)\*\*  
\*\* @ Base.MainInclude ./client.jl:451\*\*  
\*\* [3] top-level scope\*\*  
\*\* @ REPL[1]:1\*\*  
**in expression starting at /home/browni/LasthrimProjection/plot.jl:7**

---

<div class="post-metadata">

### Author: ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)
#### Post date: [September 26, 2022, 12:42pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/2 "2022-09-26T12:42:08Z")

</div>

> [@Freya\_the\_Goddess](#):
>
> `f(x) = x*(sin(x^(2))+1`

There is a **missing comma or )** here.

---

<div class="post-metadata">

### Author: ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)
#### Post date: [September 26, 2022, 12:45pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/3 "2022-09-26T12:45:06Z")

</div>

`Plots.plot()` and `frame()` won’t draw onto the same canvas. I’ve never tried to use Plots and Luxor at the same time - I don’t think it’s possible, but I’m happy if I’m wrong… 🙂

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [September 26, 2022, 1:19pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/4 "2022-09-26T13:19:10Z")

</div>

I forgot this, but remember again, thus I can’t plot the graph easily then.

---

<div class="post-metadata">

### Author: ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)
#### Post date: [September 27, 2022, 7:04am UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/5 "2022-09-27T07:04:18Z")

</div>

Here’s a quick version in Luxor.jl of `f(x) = sin(2x) * cos(x/2)`, using Zygote and code from @nilshg’s [StackOverflow answer](https://stackoverflow.com/a/66238889).

![slope](https://global.discourse-cdn.com/julialang/original/3X/7/1/71dddb1592b84aa0af43ebef0b8b1a0ee7dd36c7.gif)

> **Julia code**
>
> ```julia
> using Luxor
> using Zygote
> 
> ## mathspace to drawingspace
> K = 400/2 / 2π
> Pt(x, y) = Point(K * x, -K * y)
> 
> f(x) = sin(2x) * cos(x/2)
> 
> gradient_line(f, x₀) = (x -> f(x₀) + f'(x₀) * (x - x₀))
> 
> function drawcurve(w, h)
> @layer begin
> setopacity(0.25)
> rule(O)
> rule(O, π/2)
> end
> move(Pt(-2π, 0))
> for x in -2π:π/24:2π
> line(Pt(x, f(x)))
> end
> strokepath()
> end
> 
> function frame(scene, framenumber)
> w, h = scene.movie.width, scene.movie.height
> background("black")
> sethue("gold")
> drawcurve(w, h)
> x = rescale(framenumber, 1, scene.framerange.stop, -2π, 2π)
> pt = Pt(x, f(x))
> circle(pt, 5, :fill)
> δ = 0.1
> y = gradient_line(f, x)(x)
> point_on_curve = Pt(x, y)
> 
> y1 = gradient_line(f, x)(x - δ)
> y2 = gradient_line(f, x)(x + δ)
> 
> sl = slope(Pt(x - δ, y1), Pt(x + δ, y2))
> sethue("white")
> line(point_on_curve - polar(100, sl), 
> point_on_curve + polar(100, sl), :stroke)
> end
> 
> demo = Movie(400, 300, "slope")
> animate(demo, [Scene(demo, frame, 1:100)], framerate=10, creategif=true)
> 
> ```

This isn’t to say that this is the best or only way to write it - it’s probably easier in Plots or Makie or Javis, although I’m not familiar enough with those packages to know for sure.

Although most Julia packages usually work well together, I’d recommend using only one of the “graphical output” packages in a session. The least of the problems will be having multiple definitions for common functions; accessing the output ‘channels’ of other modules could require some advanced knowledge of their internals.

---

<div class="post-metadata">

### Author: ![icweaver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/icweaver/32/45764_2.png) [@icweaver](https://discourse.julialang.org/u/icweaver)
#### Post date: [September 27, 2022, 6:39pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/6 "2022-09-27T18:39:26Z")

</div>

That’s really cool! I like how Luxor takes care of keeping the length of the tangent line constant for us. This is what comes to mind for trying something similar in Makie (just manually applying `Luxor.slope`)

![test](https://global.discourse-cdn.com/julialang/original/3X/d/8/d8ebd83c6cabb7dcf15d494574ecc401d63bce7c.gif)

> **Julia code**
>
> ```julia
> using CairoMakie, Zygote
> 
> f(x) = sin(2x) * cos(x/2)
> gradient_line(f, x₀) = (x -> f(x₀) + f'(x₀) * (x - x₀))
> 
> with_theme(theme_dark()) do
> fig = Figure()
> ax = Axis(fig[1, 1]; limits=(-2π, 2π, -3, 3))
> 
> # Static plot setup
> x = -2π:π/24:2π
> lines!(ax, x, f)
> r_line = 1
> 
> # Animated point setup
> x_point = Observable(x[begin])
> y_point = @lift f($x_point)
> 
> # Animated line setup
> x_line = @lift begin
> m_line = f'($x_point)
> x_lim = r_line * cos(mod2pi(atan(m_line)))
> range($x_point - x_lim, $x_point + x_lim, 100)
> end
> y_line = @lift gradient_line(f, $x_point).($x_line)
> 
> # Plot line and point
> lines!(ax, x_line, y_line; color=:goldenrod)
> scatter!(ax, x_point, y_point; color=:goldenrod)
> 
> # Animate
> record(fig, "test.gif", x; framerate=15) do xi
> x_point[] = xi
> end
> end
> 
> ```

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [September 28, 2022, 9:09am UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/7 "2022-09-28T09:09:54Z")

</div>

I was trying to make a code works for the old conventional Plots, because I think Luxor is way of my league now… thanks again @cormullion

---

<div class="post-metadata">

### Author: ![Freya\_the\_Goddess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/freya_the_goddess/32/36835_2.png) [@Freya\_the\_Goddess](https://discourse.julialang.org/u/Freya_the_Goddess)
#### Post date: [September 28, 2022, 10:31am UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/8 "2022-09-28T10:31:41Z")

</div>

But I got errors trying Makie’ code of yours (using IJulia):

**`Makie.convert_arguments` for the plot type Scatter{Tuple{Float64, Float64}} and its conversion trait Makie.PointBased() was unsuccessful.**

**The signature that could not be converted was:**  
**::Float64, ::Float64**

**Makie needs to convert all plot input arguments to types that can be consumed by the backends (typically Arrays with Float32 elements).**  
**You can define a method for `Makie.convert_arguments` (a type recipe) for these types or their supertypes to make this set of arguments convertible (See [http://makie.juliaplots.org/stable/recipes.html](http://makie.juliaplots.org/stable/recipes.html)).**

**Alternatively, you can define `Makie.convert_single_argument` for single arguments which have types that are unknown to Makie but which can be converted to known types and fed back to the conversion pipeline.**

---

<div class="post-metadata">

### Author: ![icweaver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/icweaver/32/45764_2.png) [@icweaver](https://discourse.julialang.org/u/icweaver)
#### Post date: [September 28, 2022, 5:50pm UTC](https://discourse.julialang.org/t/need-help-to-create-animation-for-tangent-line-with-luxor/87809/9 "2022-09-28T17:50:35Z")

</div>

Could it be that you are using an older version of Makie? `scatter` should be able to handle `Tuple{Float64, Float64}` just fine I believe, e.g., `scatter((1., 2.))`. This is my current environment:

```julia
  [13f3f980] CairoMakie v0.8.13
  [e88e6eb3] Zygote v0.6.49

```

on Makie v0.17.13
