Problems creating Plots.jl recipes for custom types

I’m trying to implement plotting functions for my custom types as seen in Recipes · Plots.

However, I cannot seem to make it work using custom parametric types. For example, take the following struct and recipe.

struct Point{T<: Integer}
x::T
y::T
end

@recipe f(::Type{Point},P::Point) = P.x, P.y

That seems to be what I have to implement in order to be able to convert a Point to something that can be plotted ( a tuple of integers).

However, when I do that I get the following output:

julia> using Plots

julia> struct Point{T<:Integer}
       x::T
       y::T
       end
julia> @recipe f(::Type{Point}, P::Point) = P.x, P.y

julia> P = Point(3,3)
Point{Int64}(3, 3)

julia> plot(P)
ERROR: No user recipe defined for Point{Int64}
[...]

I also tried to define a “User Recipe” for a given Point in the following manner:

julia> @recipe function f(P::Point)
       x = P.x
       y = P.y
       seriestype --> :scatter
       [(x,y)]
       end

This does work when I call plot(P)and gives the correct output. However it feels a bit “hacky” having to return an array of 1 tuple instead of just the tuple. It also does not work on arrays of Points:

julia> [P,P,P]
3-element Array{Point{Int64},1}:
 Point{Int64}(3, 3)
 Point{Int64}(3, 3)
 Point{Int64}(3, 3)

julia> plot(ans)
ERROR: No user recipe defined for Point{Int64}
[...]

Can someone give some pointers on how to implement this? Specially the part about it working on arrays of points, since that is what I can’t seem to get to work.

If you define it like this, you have to call it like this, e.g.

plot( Point, P )

But it won’t show anything. But, you figured the right solution already out.
And finally you could specify the recipe for Arrays of Points like so

@recipe f( AP::AbstractArray{<:Point} ) = map( p->p.x, AP), map( p->p.y, AP )
1 Like

I assumed defining a recipe for Point would call each of them individually when passed an array, but this solution did work, thanks!