# GLMakie plot-help 2: Issue with arrows and sliders

**URL:** https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168
**Category:** New to Julia
**Tags:** glmakie
**Created:** [December 26, 2022, 9:14pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168 "2022-12-26T21:14:27Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![manya](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@manya](https://discourse.julialang.org/u/manya)
#### Post date: [December 26, 2022, 9:14pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/1 "2022-12-26T21:14:27Z")

</div>

Hi,

This is second post related to [https://discourse.julialang.org/t/glmakie-beginners-help-multiple-sliders-and-an-arrow/92113](https://discourse.julialang.org/t/glmakie-beginners-help-multiple-sliders-and-an-arrow/92113).  
Currently: I am facing the following issues:

1. Arrow heads pointing in the other direction: If I switch the base and head then it works fine[see figure of point 3]. 😯

```julia
arrows!(ax1, xbase, ybase, xhead, yhead)
#replaced with 
arrows!(ax1, xhead, yhead, xbase, ybase)

```

1. How to get the point coordinates on the figure? GLMakie does not recognize the following:

```julia
refpoint = @lift(Point($xreference,$yreference))
scatter!(refpoint, color = :red, markersize = 20)

arrowheadpoint = @lift(Point(xhead,yhead))
scatter!(arrowheadpoint, color = :blue, markersize = 20)

```

1. Creating another figure with multiple arrows all together but still using sliders: is that possible? For example, create a slider with 3 points then plot all the arrows?  
 ![Image 2022-12-25 at 9.32 PM](https://global.discourse-cdn.com/julialang/original/3X/9/9/99526b4ee68f1206e49f9dbf965e045218f8b978.jpeg)

Is the following strategy correct?

```julia
#Create a observables list [refpoint1, refpoint2, refpoint3, refpoint4]
b1 = [-4, 2, 6, -5] 
b2 = [16, 8, -18, -15]
#Create a list [arrowheadpoint1, arrowheadpoint2, arrowheadpoint3, arrowheadpoint4] 
h1 = [(x/(1 + 2 * 0.5 * r(x,y,0.5))) for x in b1, y in b2]
h2 = [y + r(x,y,0.5) for x in b1, y in b2]

#plot corresponding 4 arrows
arrows!(b1, b2, h1, h2, arrowsize = 0.2, lengthscale = 0.3)

```

The code so far with all the tries is attached here!

```julia
using GLMakie
using GeometryBasics
fig = Figure(resolution = (3456, 2234)) 
ax1 = fig[1, 1] = Axis(fig,
    # borders
    aspect = 1, limits = ((-10, 10), (-10, 10)),
    # title
    title = "sliders demo",
    titlegap = 48, titlesize = 60,
    # x-axis
    xautolimitmargin = (0, 0), xgridwidth = 2, xticklabelsize = 36,
    xticks = LinearTicks(20), xticksize = 18,
    # y-axis
    yautolimitmargin = (0, 0), ygridwidth = 2, yticklabelpad = 14,
    yticklabelsize = 36, yticks = LinearTicks(20), yticksize = 18
)

# darken axes

vlines!(ax1, [0], linewidth = 2)
hlines!(ax1, [0], linewidth = 2)

# create sliders

lsgrid = labelslidergrid!(fig,
    ["scale", "xcoordinate", "ycoordinate"],
    Ref(LinRange(-10:0.01:10));
    formats = [x -> "$(round(x, digits = 2))"],
    labelkw = Dict([(:fontsize, 30)]),
    sliderkw = Dict([(:linewidth, 24)]),
    valuekw = Dict([(:fontsize, 30)])
)

# set starting position for scale

set_close_to!(lsgrid.sliders[1], 1.0)

# layout sliders

sl_sublayout = GridLayout(height = 150)
fig[2, 1] = sl_sublayout
fig[2, 1] = lsgrid.layout

# create listener

scale = lsgrid.sliders[1].value

xreference = lsgrid.sliders[2].value

yreference = lsgrid.sliders[3].value

# arrow base points
xbase = @lift([$xreference])
ybase = @lift([$yreference])

refpoint = @lift(Point($xreference,$yreference))
scatter!(refpoint, color = :red, markersize = 20)

x = -10:0.01:10

m = @lift($scale .* x.^2)

d = @lift(1 ./ (2 .* $scale) .+ (1 ./(2 .* $scale)) .* cbrt.((13.5) .* $scale.^2 .* x.^2))

the_max = max(f(X[end]), g(X[1]))

#plot(X, f, fill = (the_max, 0.5, :auto))

line1 = lines!(ax1, x, m, color = :blue, linewidth = 5)
line2 = lines!(ax1, x, d, color = :red, linewidth = 5)

x = -10:0.01:10

p(x,y,scale) = -(2* scale *y-1)^2/(12 * scale^2) #p

q(x,y,scale) = ((2 * scale * y-1)^3-(27* scale^2) * (x^2))/(108 * scale^3) #q

del(x,y,scale) = ((27 * scale^2 * x^2 - 2((2 * scale * y)-1)^3) * x^2)/(1728* scale^4) #delta

r(x,y,scale) = del(x,y,scale) ≥ 0 ? (-(scale * y+1)/(3* scale) + cbrt(-q(x,y, scale)/2 + sqrt(del(x,y, scale))) + cbrt(-q(x,y, scale)/2 - sqrt(del(x,y, scale)))) : -(scale * y+1)/(3* scale) + (abs(2* scale *y+1)/(3* scale))* cos((1/3) * acos((-q(x,y, scale)/2)/(-p(x,y, scale)/3)^(3/2))) #piecewise expression

xhead = lift(xreference, yreference, scale) do x, y, s
    return [x/(1 + 2 * s * r(x,y,s))]
end
yhead = lift(xreference, yreference, scale) do x, y, s
    return [y + r(x,y,s)]
end

arrowheadpoint = @lift(Point(xhead,yhead))
scatter!(arrowheadpoint, color = :blue, markersize = 20)

arrows!(ax1, xbase, ybase, xhead, yhead)

#Figure 1
display(fig)

#Figure 2
#Create a observables list [refpoint1, refpoint2, refpoint3, refpoint4]
b1 = [-4, 2, 6, -5] 
b2 = [16, 8, -18, -15]
#Create a list [arrowheadpoint1, arrowheadpoint2, arrowheadpoint3, arrowheadpoint4] 
h1 = [(x/(1 + 2 * 0.5 * r(x,y,0.5))) for x in b1, y in b2]
h2 = [y + r(x,y,0.5) for x in b1, y in b2]

#plot corresponding 4 arrows
arrows!(b1, b2, h1, h2, arrowsize = 0.2, lengthscale = 0.3)

```

Thanks so much for your time! Any help with the code restructuring comments/criticisms and hints/references is highly appreciated.:).

---

<div class="post-metadata">

### Author: ![garrek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/garrek/32/27937_2.png) [@garrek](https://discourse.julialang.org/u/garrek)
#### Post date: [December 26, 2022, 11:14pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/2 "2022-12-26T23:14:49Z")

</div>

As mentioned by others in the previous post, you should create what is called a “minimum working example” (MWE). This should be a very simple example that will run that demonstrates the problem you are having. The code you provided does not run and has quite a lot of complexities that are probably not necessary, but make it difficult for other people to read your code.

Related, whenever I try to do something complicated and new, I try to create a very simple example with _only_ the elements that I need. Then when it works I can add complexity. If I were doing your project, for example, I would just start with something like a horizontal line or single parabola and a single arrow. Then build up from there.

With that in mind, I tried to simplify your code so that it will run. I left just a single arrow so that we can get that working. I don’t have time right now to try to get it to work the way I think you want, but I at least wanted to demonstrate how to make a MWE and try to understand your code better.

To answer your question, it should be possible to create three responsive arrows, but let’s start by getting _one_ working. 😉

Some notes on what I did:

- Removed GeometryBasics package. I don’t see why you need this. (Maybe I’m wrong)
- Updated syntax for the latest GLMakie (v0.8.0). Particularly using `SliderGrid`, as I mentioned in the previous post. (A lot has changed with many bug fixes. Of course if you have a very good reason for using the older version, let us know.)
- Deleted a bunch of unnecessary code so that I can see how you are making just a single arrow that depends on `xreference`, `yreference`, and `scale`.

What I might try next:  
I think the bones of what you want to do are there (for just this one arrow). I think I would adjust the equations you are using to calculate the endpoints, since I don’t think it is pointing at what you want. I don’t quite understand how you are calculating the arrow. The equations look pretty complicated and have some hard-coded values (`1728`?) that I don’t understand.

**MWE** :

```julia
using GLMakie

fig = Figure()
display(fig)
ax1 = Axis(fig[1, 1])

xlims!(-10, 10)
ylims!(-10, 10)

lsgrid = SliderGrid(fig[1, 2],
    (label = "scale", range = -10:0.01:10, format = "{:.1f}", startvalue = 1),
    (label = "xcoordinate", range = -10:0.01:10, format = "{:.1f}", startvalue = 1), 
    (label = "ycoordinate", range = -10:0.01:10, format = "{:.1f}", startvalue = 1),
    tellheight = false
)

scale = lsgrid.sliders[1].value
xreference = lsgrid.sliders[2].value
yreference = lsgrid.sliders[3].value

# arrow base points
xbase = @lift([$xreference])
ybase = @lift([$yreference])

refpoint = @lift(Point2f($xreference, $yreference))
scatter!(refpoint, color = :red, markersize = 20)

x = -10:0.01:10
m = @lift($scale .* x.^2)
d = @lift(1 ./ (2 .* $scale) .+ (1 ./ (2 .* $scale)) .* cbrt.((13.5) .* $scale.^2 .* x.^2))

line1 = lines!(ax1, x, m, color = :blue, linewidth = 5)
line2 = lines!(ax1, x, d, color = :red, linewidth = 5)

x = -10:0.01:10
p(x, y, scale) = -(2 * scale * y - 1)^2 / (12 * scale^2) #p
q(x, y, scale) = ((2 * scale * y - 1)^3 - (27 * scale^2) * (x^2)) / (108 * scale^3) #q
del(x, y, scale) = ((27 * scale^2 * x^2 - 2((2 * scale * y) - 1)^3) * x^2) / (1728 * scale^4) #delta
r(x, y, scale) = del(x, y, scale) ≥ 0 ? (-(scale * y + 1)/(3* scale) + cbrt(-q(x, y, scale)/2 + sqrt(del(x, y, scale))) + cbrt(-q(x, y, scale) / 2 - sqrt(del(x, y, scale)))) : -(scale * y + 1) / (3 * scale) + (abs(2 * scale * y + 1) / (3 * scale)) * cos((1/3) * acos((-q(x, y, scale) / 2) / (-p(x, y, scale) / 3)^(3/2))) #piecewise expression

xhead = lift(xreference, yreference, scale) do x, y, s
    return [x / (1 + 2 * s * r(x, y, s))]
end
yhead = lift(xreference, yreference, scale) do x, y, s
    return [y + r(x, y, s)]
end

arrows!(ax1, xbase, ybase, xhead, yhead)

```

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [December 26, 2022, 11:23pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/3 "2022-12-26T23:23:47Z")

</div>

Regarding the `arrows!`: I used a bit of a wrong notation for the example I gave in [GLMakie beginners help: Multiple sliders and an arrow - #3 by fatteneder](https://discourse.julialang.org/t/glmakie-beginners-help-multiple-sliders-and-an-arrow/92113/3)  
E.g. I used `xbase, ybase, xhead, yhead`.  
Just took another look at the docstring (try `?arrow` in the `REPL`) and noticed that `arrows` wants arguments like `arrows!(ax1, x, y, u, v)` where `x,y` refer to the base point of the arrow(s) to draw and `u, v` are the directions of the arrow(s) as seen from the base points.

Maybe that helps with clearing up the arrows formulae.

---

<div class="post-metadata">

### Author: ![manya](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@manya](https://discourse.julialang.org/u/manya)
#### Post date: [December 27, 2022, 12:25am UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/4 "2022-12-27T00:25:42Z")

</div>

> [@fatteneder](#):
>
> arrows

Thanks Garek, I see one quick issue in this MWE. The reference point should not be on parabola but rather the arrow head should be on the parabola[always]. How to fix that? I double checked equations are mathematically correct. I will still look at it again for one more day.

---

<div class="post-metadata">

### Author: ![manya](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@manya](https://discourse.julialang.org/u/manya)
#### Post date: [January 1, 2023, 10:55pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/5 "2023-01-01T22:55:49Z")

</div>

Since u and v are direction vectors: so for two points (x\_1,x\_2) and (y\_1,y\_2), (u,v) will be (x\_2-x\_1, y\_2-y\_1)? Do I need to lift those[to work with the sliders] as well in this MWE?

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [January 1, 2023, 11:03pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/6 "2023-01-01T23:03:54Z")

</div>

If you want the arrows to properly react to your sliders, then yes.

---

<div class="post-metadata">

### Author: ![manya](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@manya](https://discourse.julialang.org/u/manya)
#### Post date: [January 1, 2023, 11:49pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/7 "2023-01-01T23:49:21Z")

</div>

```julia
xhead = lift(xreference, yreference, α) do x, y, s
    return [x / (1 + 2 * s * r(x, y, s))]
end
yhead = lift(xreference, yreference, α) do x, y, s
    return [y + r(x, y, s)]
end

xdir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [u - x]
end

ydir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [v - y]
end

arrows!(ax1, xbase, ybase, xdir, ydir)

```

Is this the right way to lift (u,v)? The reason I lift without reference @ and $xhead, $yhead, because these two variables/observables are already referenced before?

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [January 1, 2023, 11:59pm UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/8 "2023-01-01T23:59:08Z")

</div>

yes looks good  
did you not try it?

---

<div class="post-metadata">

### Author: ![manya](https://avatars.discourse-cdn.com/v4/letter/m/bcef8e/32.png) [@manya](https://discourse.julialang.org/u/manya)
#### Post date: [January 2, 2023, 12:06am UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/9 "2023-01-02T00:06:42Z")

</div>

Theoretically the above is correct: but throw out

```julia
MethodError: no method matching -(::Vector{Float64}, ::Float64).

```

I can see the dimension mismatch of (xbase, ybase) being vectors[based on the sliders range input] and (xdir, ydir) being scalars. How to use lifting in such a case

```julia
xdir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [u - x]
end

ydir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [v - y]
end

```

so that (xdir, ydir) is also a vector?

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [January 2, 2023, 10:00am UTC](https://discourse.julialang.org/t/glmakie-plot-help-2-issue-with-arrows-and-sliders/92168/10 "2023-01-02T10:00:31Z")

</div>

I assume you defined `xreference, yreference, xhead, yhead` as in my post here: [GLMakie beginners help: Multiple sliders and an arrow - #3 by fatteneder](https://discourse.julialang.org/t/glmakie-beginners-help-multiple-sliders-and-an-arrow/92113/3)

As you say the problem is a dimension mismatch: `[xy]head` being (an observable of) a vector and `[xy]reference` being (an observable of ) a scalar.  
Since your vectors `[xy]base` only have one component, just use

```julia
xdir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [u[1] - x ]
end

ydir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [v[1] - y ]
end

```

In the other post I did not anticipate that there might be a dimension mismatch.  
So perhaps it would be good to re-organize the code a bit. Building on top of @garrek’s MWE from above:

```julia
using GLMakie

fig = Figure()
display(fig)
ax1 = Axis(fig[1, 1])

xlims!(-10, 10)
ylims!(-10, 10)

lsgrid = SliderGrid(fig[1, 2],
    (label = "scale", range = -10:0.01:10, format = "{:.1f}", startvalue = 1),
    (label = "xcoordinate", range = -10:0.01:10, format = "{:.1f}", startvalue = 1), 
    (label = "ycoordinate", range = -10:0.01:10, format = "{:.1f}", startvalue = 1),
    tellheight = false
)

scale = lsgrid.sliders[1].value
xreference = lsgrid.sliders[2].value
yreference = lsgrid.sliders[3].value

# arrow base points
xbase = @lift([$xreference])
ybase = @lift([$yreference])

refpoint = @lift(Point2f($xreference, $yreference))
scatter!(refpoint, color = :red, markersize = 20)

x = -10:0.01:10
m = @lift($scale .* x.^2)
d = @lift(1 ./ (2 .* $scale) .+ (1 ./ (2 .* $scale)) .* cbrt.((13.5) .* $scale.^2 .* x.^2))

line1 = lines!(ax1, x, m, color = :blue, linewidth = 5)
line2 = lines!(ax1, x, d, color = :red, linewidth = 5)

x = -10:0.01:10
p(x, y, scale) = -(2 * scale * y - 1)^2 / (12 * scale^2) #p
q(x, y, scale) = ((2 * scale * y - 1)^3 - (27 * scale^2) * (x^2)) / (108 * scale^3) #q
del(x, y, scale) = ((27 * scale^2 * x^2 - 2((2 * scale * y) - 1)^3) * x^2) / (1728 * scale^4) #delta
r(x, y, scale) = del(x, y, scale) ≥ 0 ? (-(scale * y + 1)/(3* scale) + cbrt(-q(x, y, scale)/2 + sqrt(del(x, y, scale))) + cbrt(-q(x, y, scale) / 2 - sqrt(del(x, y, scale)))) : -(scale * y + 1) / (3 * scale) + (abs(2 * scale * y + 1) / (3 * scale)) * cos((1/3) * acos((-q(x, y, scale) / 2) / (-p(x, y, scale) / 3)^(3/2))) #piecewise expression

# compute base point of arrow
xhead = lift(xreference, yreference, scale) do x, y, s
    return x / (1 + 2 * s * r(x, y, s))
end
yhead = lift(xreference, yreference, scale) do x, y, s
    return y + r(x, y, s)
end
# compute direction of arrow
xdir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [u - x]
end

ydir = lift(xreference, yreference, xhead, yhead) do x, y, u, v
    return [v - y]
end

# promote arrow data to vectors for usage with arrows! below
v_xhead = @lift([$xhead])
v_yhead = @lift([$yhead])
v_xdir = @lift([$xdir])
v_ydir = @lift([$ydir])

arrows!(ax1, xbase, ybase, xdir, ydir)

```
