Single Vertex with Self Edge cannot be plotted?
Attempting to plot the graph with 1 node and 1 self edge fails.
G = SimpleGraph(1)
add_edge!(G, 1, 1 )
graphplot( G)
BoundsError: attempt to access 1×1 Array{Float64,2} at index [2, 1]
Stacktrace:
[1] getindex at ./array.jl:745 [inlined]
[2] stress at /home/caseykneale/.julia/packages/GraphRecipes/9n0SL/src/graph_layouts.jl:160
...
I think the issue is the force directed plot mechanism doesn't handle this case because... its weird!
You are quite good at finding weird use cases! :wink:
You are right that there is a problem with the force layout mechanism, but that is not the only problem...
G = Graph(1)
add_edge!(G, 1, 1)
graphplot(G,x=[1],y=[2])
BoundsError: attempt to access 0-element Array{Float64,1} at index [0]
Stacktrace:
[1] getindex at ./array.jl:744 [inlined]
[2] unoccupied_angle(::Float64, ::Float64, ::Array{Int64,1}, ::Array{Int64,1}) at /home/jackd/.julia/packages/GraphRecipes/1lk2O/src/utils.jl:202
[3] macro expansion at /home/jackd/.julia/packages/GraphRecipes/1lk2O/src/graphs.jl:602 [inlined]
[4] macro expansion at /home/jackd/.julia/packages/RecipesBase/zBoFG/src/RecipesBase.jl:312 [inlined]
[5] macro expansion at /home/jackd/.julia/packages/GraphRecipes/1lk2O/src/graphs.jl:478 [inlined]
[6] apply_recipe(::Dict{Symbol,Any}, ::GraphRecipes.GraphPlot) at /home/jackd/.julia/packages/RecipesBase/zBoFG/src/RecipesBase.jl:275
[7] _process_userrecipes(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}, ::Tuple{GraphRecipes.GraphPlot}) at /home/jackd/.julia/packages/Plots/qZHsp/src/pipeline.jl:83
[8] _plot!(::Plots.Plot{Plots.GRBackend}, ::Dict{Symbol,Any}, ::Tuple{GraphRecipes.GraphPlot}) at /home/jackd/.julia/packages/Plots/qZHsp/src/plot.jl:178
[9] #plot#138(::Base.Iterators.Pairs{Symbol,Array{Int64,1},Tuple{Symbol,Symbol},NamedTuple{(:x, :y),Tuple{Array{Int64,1},Array{Int64,1}}}}, ::typeof(plot), ::GraphRecipes.GraphPlot) at /home/jackd/.julia/packages/Plots/qZHsp/src/plot.jl:57
[10] #plot at ./none:0 [inlined]
[11] #graphplot#72 at /home/jackd/.julia/packages/RecipesBase/zBoFG/src/RecipesBase.jl:350 [inlined]
[12] (::GraphRecipes.var"#kw##graphplot")(::NamedTuple{(:x, :y),Tuple{Array{Int64,1},Array{Int64,1}}}, ::typeof(graphplot), ::SimpleGraph{Int64}) at ./none:0
[13] top-level scope at In[23]:3
I made a, probably bad, prototype for a solution to this... If its not useful I understand but at least I tried!
using Plots
x_0, y_0 = 1.0, 1.0
lobes = 1 #aka self edges
pnts_per_lobe = 50
θ = ( 1 : (360 / ( lobes * pnts_per_lobe ) ) : 360 ) * (pi / 180.0)
if lobes != 1
#Rotated cardiod
x = ( 2. .* (1. .- cos.( lobes .* θ ))) .* cos.( θ ) .+ x_0
y = ( 2. .* (1. .- cos.( lobes .* θ ))) .* sin.( θ ) .+ y_0
else
#Rosette
x = cos.(lobes*θ) .* cos.(θ) .+ x_0
y = cos.(lobes*θ) .* sin.(θ) .+ y_0
end
scatter( [x_0], [y_0] , label = "fancy point")
plot!( x, y )
somewhat improved solution...
using Plots
function K1_Plot(self_edges = 1, pnts_per_edge = 50)
θ = ( 1 : (360 / ( self_edges * pnts_per_edge ) ) : 360 ) * (pi / 180.0)
coefficient = (self_edges != 1 ) ? 2. .* (1. .- cos.( self_edges .* θ )) :
cos.(self_edges*θ)
plot(coefficient .* cos.( θ ), coefficient .* sin.( θ ),
label = "", xlabel = "", ylabel = "",
xaxis = false, yaxis = false)
a = scatter!( [0.0], [0.0] , label = "")
return a
end
K1_Plot(5)
What is that code trying to achieve? self edges are already possible, right, just not if you only have one vertex?
Agreed, I don't see how this would solve the issue being raised.
Having said that the lobes may be slightly more aesthetically pleasing way to do self edges than our current method. When tackling #100 , I think that it might be worthwhile to talk about whether self-edges could be made to look nicer too.
@mkborregaard -- unrelated: I have written up some project ideas (as issues) for VizCon and labelled them with the VizCon tag in this repo. If I get more time before Wednesday, then I may add some more detail/hints to some of them. Otherwise, I think that all of the proposed projects are good to go. Best of luck for the conference, I hope that it goes well :smile:
So awesome! We'll promote them, hope someone bites! I've added most of them to the vizcon2 project too
What is that code trying to achieve? self edges are already possible, right, just not if you only have one vertex?
the function K1_Plot is just an example of how someone could plot single vertices with N self edges in a mostly self consistent way. Examples: https://en.wikipedia.org/wiki/Bouquet_graph https://mathworld.wolfram.com/BouquetGraph.html
I realize this is not how you all are plotting the other graphs, but one solution(admittedly a bad one) would be to generate a specific case for this. I'm not a very talented julia developer, I just know how to do the things I need to do. I used this code for a fix in my blog (https://nextjournal.com/a/MGJFGtLSLpwk3eCdknBVQ?token=GA19Dbu1JJdzrwByeGRiAr).
I agree that the function is a nice way to solve that particular case. Although if we find a way to use the exsisting self-edge functionality to solve this problem (which i think that we will), then that would be preferable. That way users wouldn't be surprised by the fact that the way self-edges get displayed depends on how many nodes are in the graph. In the end, I decided not to go with the bouqet style. The reason being that before plotting a self edge, graphplot will look for an "unoccupied angle" and then plot all self-edges in that direction to minimise self-edge collisions with other edges.
I'm not a very talented julia developer...
Please don't take our critiques on your solution personally. On these forums we critique everybodies solutions. We don't do so to prove that we are the best Julia developers ever, rather we just want to make sure that any code that goes into the repo is thought about carefully. We encourage feedback from all perspectives to try and produce the best possible solution.