# Makie @recipe need understanding

**URL:** <https://discourse.julialang.org/t/makie-recipe-need-understanding/102563>\
**Category:** General Usage\
**Tags:** question, makie\
**Created:** [August 7, 2023, 1:43pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563 "2023-08-07T13:43:21Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 7, 2023, 1:43pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/1 "2023-08-07T13:43:21Z")

</div>

I’m having no luck finding a working example of how to define a makie @recipe for a custom type, or in this case custom types.

I have a home grown quaternion and a 3D vector type which match better how legacy simulations function making conversion better. The Vector type presents an x, y, and z field. The quaternion can rotate those vectors.

In Plots.jl recipe it is fairly easy to specify a plot overload that throws up 3 lines representing the XYZ axis of a quaternion rotation into a plot where I have an optional origin for the axis and a scale factor for the length of the axis.

The Plot.jl recipe I’m trying to emulate starts out with a from like this.

```julia
quaternion_plot
@recipe function f(q::quaternion, v::xyzVecT = xyzVecT(); scalefactor = 1.0)
# Quaternion will plot the X, Y and Z axis at the location
    seriestype := :path
    linestyle --> :solid
    arrow --> :True
    seriesalpha --> 0.4
    marker --> :none
    xaxis = xVec(scalefactor) * q
    yaxis = yVec(scalefactor) * q
    zaxis = zVec(scalefactor) * q
    quickFmt(a,b) = [a.x,b.x], [a.y, b.y], [a.z, b.z]
    # Plot the X Axis in Blue with reduced alpha
    @series begin
        label --> :none
        seriescolor --> :blue
        marker := :none
        quickFmt(v, v + xaxis) # Remove the vector markers
    end
    @series begin
        label --> :none
        seriescolor --> :green
        marker := :none
        quickFmt(v, v + yaxis) # Remove the vector markers
    end
    @series begin
        label --> :none
        seriescolor --> :red
        marker := :none
        quickFmt(v, v + zaxis) # Remove the vector markers
    end

    # Direction Pointers
    @series begin
        label --> "X"
        seriestype --> :scatter
        seriescolor --> :blue
        marker := :diamond
        temp=v + xaxis
        [temp.x], [temp.y], [temp.z]
    end

    @series begin
        label --> "Y"
        seriestype --> :scatter
        seriescolor --> :green
        marker := :circle
        temp=v + yaxis
        [temp.x], [temp.y], [temp.z]
    end

    @series begin
        label --> "Z"
        seriestype --> :scatter
        seriescolor --> :red
        marker := :square
        temp=v + zaxis
        [temp.x], [temp.y], [temp.z]
    end

end

```

I cannot figure out how to get the Makie.@recipe to do anything, even if I skip the origin shift and the scale factor and just take the quaternion. I find just the one documentation example and a dataframe example on the internet. Can someone help me understand this @recipe concept and figure out how to use it or is it just too far off and I need to forget a recipe.

```julia
@recipe(QPlot, q, origin, scale_factor ) do scene
        Attributes(
            color = :red,
            style = :dashed
        )
    end

function plot!(qp::QPlot)
        xaxis = xVec(qp[:scale_factor][]) * qp[:q][]
        yaxis = yVec(qp[:scale_factor][]) * qp[:q][]
        zaxis = zVec(qp[:scale_factor][]) * qp[:q][]
        quickFmt(a,b) = [a.x,b.x], [a.y, b.y], [a.z, b.z]
        lines!(qp,quickFmt(qp[:origin], qp[:origin] + xaxis),color=qp[:color][],linestyle=qp[:style][])
        lines!(qp,quickFmt(qp[:origin], qp[:origin] + yaxis),color=qp[:color][],linestyle=qp[:style][])
        lines!(qp,quickFmt(qp[:origin], qp[:origin] + zaxis),color=qp[:color][],linestyle=qp[:style][])
        qp
    end

```

Note: I’m assuming the quickFmt works the same for lines! as it did for the plot recipe, but I haven’t even gotten into the function to debug any of that stuff.

Thanks for any help and understanding.  
Best Regards,  
Allan

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 7, 2023, 2:01pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/2 "2023-08-07T14:01:56Z")

</div>

It needs to be `Makie.plot!` if you want to extend that function, that might be the first thing to try? There are a couple things that could be improved, for example you unwrap all observables so the plot will not be interactively updateable. Might have time to write an example later.

---

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 7, 2023, 3:38pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/3 "2023-08-07T15:38:41Z")

</div>

yeah, forget the observable unwrapping. I was following the DataFrame example I found, but that makes sense.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 8, 2023, 4:15am UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/4 "2023-08-08T04:15:10Z")

</div>

Try this to get started:

```julia
julia> @recipe(QPlot, q, origin, scale_factor ) do scene
           Attributes(
               color = :red,
               style = :dashed
           )
       end

julia> function Makie.plot!(p::QPlot)
           axs = lift(p[:q], p[:scale_factor], p[:origin]) do q, scale, ori
               segments = mapreduce(vcat, [Vec3f(1, 0, 0), Vec3f(0, 1, 0), Vec3f(0, 0, 1)]) do v
                   v_rot = q * (scale * v)
                   [ori, ori + v_rot]
               end
           end
           linesegments!(p, axs, color = [:red, :green, :blue])
           p
       end

julia> qplot(Makie.to_rotation(1.0), Point3f(2, 2, 2), 3.0)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/5/f/5f65744eb4dcdcdf634f7f1d2cf3ca30c627ed12.jpeg)

---

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 8, 2023, 8:25pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/5 "2023-08-08T20:25:53Z")

</div>

Whoa. That’s fancy. Thank you! I’ll give it a shot!

---

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 10, 2023, 10:49pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/6 "2023-08-10T22:49:22Z")

</div>

I think I have this part working now… in a package extension no left.  
Do you by any change know, how to have default arguments for origin and scale\_factor in this recipe or pass in kw arguments?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 11, 2023, 4:26am UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/7 "2023-08-11T04:26:23Z")

</div>

I would turn them into attributes if you need defaults and keywords.

---

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 15, 2023, 1:14pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/8 "2023-08-15T13:14:01Z")

</div>

I think I have it all working, thank you.  
I am having trouble when placing this recipe in an extension that gets loaded on MakieCore.

I don’t seem to be able to make the recipe generated plot function (quaternionplot) “external” or link back to the original module. Usually I would do something like OriginalModule.quaternionplot. But since that quaternionplot is created by the recipe, I can’t seem to make it hook up by just putting “external quaternionplot” in the extension.

I did have it working by defining empty functions in the OriginalModule for quaternionplot and quaternionplot!, but then I get a warning about broken modules because the @recipe macro was redefining it. \*\* incremental compilation may be fatally broken for this module \*\*

I don’t see how it can have it both ways. I haven’t yet seen an example that lets me understand the best practice here. Any ideas?

Best Regards,  
Allan Baker

---

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 15, 2023, 1:16pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/9 "2023-08-15T13:16:17Z")

</div>

Inside OriginalModule:

```julia
"quaternionplot requires a Makie backend to work as it is overloaded in OriginalModuleMakieExt.jl."
function quaternionplot() end

"quaternionplot! requires a Makie backend to work as it is overloaded in OriginalModuleMakieExt.jl."
function quaternionplot!() end

export quaternionplot, quaternionplot!

```

Inside extension with recipe.  
`import OriginalModule: quaternionplot, quaternionplot!`

Warning looks something like this where the I have changed some of the names to keep it generic:

```julia
 WARNING: Method definition quaternionplot() in module OriginalModule at D:\julia\development\OriginalModule\src\OriginalModule.jl:445 overwritten in module OriginalModuleMakieExt at C:\Users\username\.julia\packages\MakieCore\bttjb\src\recipes.jl:173.
│ **incremental compilation may be fatally broken for this module**

```

---

<div class="post-metadata">

**Author:** ![Allan\_Baker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_baker/32/42645_2.png) [@Allan\_Baker](https://discourse.julialang.org/u/Allan_Baker)\
**Post date:** [August 15, 2023, 1:19pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/10 "2023-08-15T13:19:07Z")

</div>

But it works. It just has nasty warnings.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 15, 2023, 3:14pm UTC](https://discourse.julialang.org/t/makie-recipe-need-understanding/102563/11 "2023-08-15T15:14:09Z")

</div>

> [@Allan\_Baker](#):
>
> `function quaternionplot() end`

If you put

```julia
function quaternionplot end # <-- no parentheses

```

instead, does it work without warning?

The latter defines an empty function (a function with no methods), whereas the former defines a function with one method (which does nothing).
