diff --git a/docs/src/literate-gallery/big_phylogeny.jl b/docs/src/literate-gallery/big_phylogeny.jl new file mode 100644 index 0000000..d263047 --- /dev/null +++ b/docs/src/literate-gallery/big_phylogeny.jl @@ -0,0 +1,37 @@ +using CairoMakie, NewickTree, BasicTreePlots, AbstractTrees + +tree = + nw"((6669.DappuP312785:1.24473,(((7739.JGI126010:4.02e-06,7739.JGI126021:0.168081)0.99985:0.848895,((45351.NEMVEDRAFT_v1g217973-PA:1.49614,(6085.XP_002167371:1.08059,10228.TriadP54105:1.08509)0.457684:0.128729)0.99985:0.321915,(7668.SPU_016633tr:0.00222941,7668.SPU_013365tr:0.093091)0.99985:0.642533)0.888302:0.101463)0.998565:0.12537,((51511.ENSCSAVP00000011400:0.259936,7719.ENSCINP00000035803:0.209259)0.99985:1.762,(7757.ENSPMAP00000006833:0.945887,((7955.ENSDARP00000103018:0.187989,(8049.ENSGMOP00000003903:0.283082,((8128.ENSONIP00000009923:0.172432,(69293.ENSGACP00000005927:0.11289,(99883.ENSTNIP00000008530:0.0637802,31033.ENSTRUP00000029741:0.0851327)0.99985:0.111539)0.750558:0.0140823)0.99985:0.0210439,(8083.ENSXMAP00000007211:0.156672,8090.ENSORLP00000021771:0.242897)0.99985:0.0332475)0.99985:0.0502247)0.99985:0.097906)0.99985:0.204816,(7897.ENSLACP00000021045:0.20103,(8364.ENSXETP00000053091:0.389689,((9258.ENSOANP00000015194:0.652603,((13616.ENSMODP00000032296:0.0669026,(9315.ENSMEUP00000005072:0.0368095,9305.ENSSHAP00000018667:0.0280404)0.997706:0.0140274)0.99985:0.109803,((9361.ENSDNOP00000011178:0.093465,(9371.ENSETEP00000005953:0.276816,(9813.ENSPCAP00000009886:0.0800451,9785.ENSLAFP00000023898:0.0550027)0.99697:0.0294647)0.99985:0.0375967)0.608183:0.00574174,((((30608.ENSMICP00000006810:0.0353003,30611.ENSOGAP00000013460:0.0515798)0.99985:0.034051,(9478.ENSTSYP00000011163:0.0656837,(9483.ENSCJAP00000037059:0.0556713,(9544.ENSMMUP00000001688:0.00821597,(61853.ENSNLEP00000001585:0.00543935,(9601.ENSPPYP00000009641:0.00544861,(9593.ENSGGOP00000014253:0.00241737,(9606.ENSP00000299886:0.00108745,9598.ENSPTRP00000016297:0.00216932)0.993995:0.00108247)0.99985:0.00217395)0.99985:0.00216928)0.99985:0.00380297)0.99985:0.00880979)0.99985:0.0259329)0.993631:0.00725957)0.99985:0.00775695,((((10141.ENSCPOP00000018381:0.0312261,10141.ENSCPOP00000003239:0.0560276)0.99985:0.131426,(10090.ENSMUSP00000018805:0.0326181,10116.ENSRNOP00000003804:0.0330137)0.99985:0.081468)0.995671:0.0105266,(43179.ENSSTOP00000001636:0.0584822,10020.ENSDORP00000002346:0.148367)0.976029:0.00712029)0.99985:0.020967,(9986.ENSOCUP00000010215:0.342444,37347.ENSTBEP00000010812:0.0710806)0.981559:0.0148504)0.99985:0.0111655)0.99985:0.0141806,((9823.ENSSSCP00000018275:0.0497089,(9739.ENSTTRP00000004916:0.0624029,9913.ENSBTAP00000007999:0.0933538)0.99985:0.0153799)0.99985:0.0353429,((9796.ENSECAP00000006507:0.0593149,(9685.ENSFCAP00000004377:0.0895056,(9615.ENSCAFP00000006718:0.0344248,(9646.ENSAMEP00000002816:0.0246918,9669.ENSMPUP00000014182:0.157245)0.979337:0.0106908)0.990824:0.00781435)0.99985:0.0209773)0.99291:0.00461526,(59463.ENSMLUP00000015199:0.175449,132908.ENSPVAP00000006353:0.0636063)0.828177:0.00861023)0.805512:0.00313751)0.99985:0.0138134)0.99985:0.0180555)0.99985:0.0925821)0.99985:0.0504324)0.99985:0.0408666,(28377.ENSACAP00000014302:0.2972,(13735.ENSPSIP00000020553:0.125656,(59729.ENSTGUP00000002997:0.21101,(9103.ENSMGAP00000006649:0.034221,9031.ENSGALP00000007041:0.0301602)0.99985:0.14558)0.99985:0.0950631)0.912514:0.0193477)0.99985:0.0543705)0.99985:0.0558399)0.99985:0.0851946)0.996306:0.0767894)0.99985:0.242292)0.99843:0.214734)0.760404:0.170331)0.99985:0.889243)0.99985:0.309174,((7070.TC009561-PA:1.414,(7029.ACYPI001869-PA:2.67503,((34740.HMEL012959-PA:0.216556,(13037.EHJ66433:0.30242,7091.BGIBMGA012450-TA:0.234676)0.691542:0.0356537)0.99985:1.06833,(7425.NV10250-PA:0.448078,(7460.GB18353-PA:0.265179,12957.ACEP_00009457-PA:0.219522)0.99985:0.223062)0.99985:0.715703)0.950323:0.0960579)0.630765:0.0828761)0.868488:0.104171,(121225.PHUM413450-PA:1.38201,(((43151.ADAR004533-PA:0.286189,7165.AGAP001322-PA:0.216522)0.99985:0.404262,(7176.CPIJ007948-PA:0.310705,7159.AAEL007141-PA:0.261808)0.99985:0.238196)0.99985:0.352684,(7260.FBpp0240708:0.24283,((7222.FBpp0149372:0.191481,7244.FBpp0224481:0.114954)0.99985:0.156407,(7237.FBpp0281462:0.118908,(7217.FBpp0120932:0.132407,(7245.FBpp0269552:0.0320153,7227.FBpp0082093:0.0340969)0.99985:0.0854297)0.99985:0.0800303)0.99985:0.0655239)0.825983:0.0710402)0.99985:1.14395)0.99985:0.708932)0.628915:0.0819834)0.99985:0.309174);" + +fig = Figure(size = (500, 500)) +ax = PolarAxis(fig[1, 1]; rautolimitmargin = (0.05, 0.1)) + +c = map(PreOrderDFS(tree)) do node + BasicTreePlots.leafcount(node) +end + +treeplot +treeplot!( + ax, + tree, + layoutstyle = :cladogram, + branchstyle = :straight, + ignorebranchlength = true, + tipannotationsvisible = true, + usemaxdepth = true, + linecolor = :gainsboro, +) +s = treescatter!( + ax, + tree, + layoutstyle = :cladogram, + branchstyle = :straight, + ignorebranchlength = true, + markercolor = log2.(c), + colormap = :inferno, + alpha = 0.5, +) +hidedecorations!(ax) +hidespines!(ax) +Colorbar(fig[1, 2][3, 1], s, label = "# leafs (log2)") +fig diff --git a/docs/src/literate-gallery/phylogeny_of_organisms.jl b/docs/src/literate-gallery/phylogeny_of_organisms.jl new file mode 100644 index 0000000..bb76ff1 --- /dev/null +++ b/docs/src/literate-gallery/phylogeny_of_organisms.jl @@ -0,0 +1,54 @@ +# # Phylogeny of some organisms +using CairoMakie, NewickTree, AbstractTrees, BasicTreePlots + +tree = + nw"(Bovine:0.69395,(Gibbon:0.36079,(Orangutan:0.33636,(Gorilla:0.17147,(Chimp:0.19268,Human:0.11927):0.08386):0.06124):0.15057):0.54939,Mouse:1.21460);" + +isprimate = Dict( + "Bovine" => false, + "Gibbon" => true, + "Orangutan" => true, + "Gorilla" => true, + "Chimp" => true, + "Human" => true, + "Mouse" => false, +) +tree_data = Dict( + node => (; + is_primate = get(isprimate, nodevalue(node).data.name, missing), + bananas_ate = 25 * rand(), + ) for node in PreOrderDFS(tree) +) + +markercolors = map(PreOrderDFS(tree)) do node + if haskey(isprimate, nodevalue(node).data.name) + if tree_data[node].is_primate + :gold + else + :black + end + else + :transparent + end +end + +markersizes = map(PreOrderDFS(tree)) do node + if haskey(isprimate, nodevalue(node).data.name) + if isprimate[nodevalue(node).data.name] + 1 + tree_data[node].bananas_ate * 2.0 + else + 1 + tree_data[node].bananas_ate * 0.5 + end + else + 0 + end +end + + +fig = Figure() +ax = Axis(fig[1, 1], xautolimitmargin = (0.0, 0.2)) +hidedecorations!(ax) +hidespines!(ax) +treeplot!(ax, tree, usemaxdepth = true) +treescatter!(ax, tree, markercolor = markercolors, markersize = markersizes) +fig diff --git a/docs/src/literate-tutorials/basics.jl b/docs/src/literate-tutorials/basics.jl index 443d020..b7315de 100644 --- a/docs/src/literate-tutorials/basics.jl +++ b/docs/src/literate-tutorials/basics.jl @@ -76,6 +76,16 @@ hidespines!(ax) treeplot!(tree; linecolor = branchcolors, tipfontsize = 12) fig +# or employ markers in the nodes to showcase the tree's information + +fig = Figure() +ax = PolarAxis(fig[1, 1], rautolimitmargin = (0.0, 0.1)) +hidedecorations!(ax) +hidespines!(ax) +treeplot!(tree; tipfontsize = 12) +treescatter!(tree; markercolor = branchcolors) +fig + # For instance if we have external data about each node in the tree tree_data = Dict( diff --git a/ext/BasicTreePlotsMakieExt.jl b/ext/BasicTreePlotsMakieExt.jl index 9e58c79..0ebb9db 100644 --- a/ext/BasicTreePlotsMakieExt.jl +++ b/ext/BasicTreePlotsMakieExt.jl @@ -1,34 +1,38 @@ module BasicTreePlotsMakieExt import BasicTreePlots -import BasicTreePlots: treeplot, treeplot! +import BasicTreePlots: + treeplot, + treeplot!, + treelabels, + treelabels!, + treescatter, + treescatter!, + treearea, + treearea!, + treecladelabel, + treecladelabel! import Makie import Makie: Point2f +import AbstractTrees +import AbstractTrees: PreOrderDFS + +# treeplot ==================================================================================== Makie.@recipe(TreePlot, tree) do scene attr = Makie.Attributes( showroot = false, layoutstyle = :dendrogram, branchstyle = :square, ignorebranchlengths = false, + openangle = 0, linevisible = true, linecolor = @something(Makie.theme(scene, :color), :black), linewidth = @something(Makie.theme(scene, :linewidth), 1), linecolormap = @something(Makie.theme(scene, :colormap), :viridis), branch_point_resolution = 25, - markervisible = false, - markercolor = @something(Makie.theme(scene, :color), :black), - markersize = @something(Makie.theme(scene, :markersize), 5), - markercolormap = @something(Makie.theme(scene, :colormap), :viridis), usemaxdepth = false, - tipannotationsvisible = true, - tipannotations = nothing, - tipfontsize = 9.0f0, - leafdata = nothing, - openangle = 0, - tipalign = @something(Makie.theme(scene, :align), (:left, :center)), - tipannotationoffset = @something(Makie.theme(scene, :offset), (3.0f0, 0.0f0)), ) Makie.MakieCore.generic_plot_attributes!(attr) return Makie.MakieCore.colormap_attributes!(attr, Makie.theme(scene, :colormap)) @@ -84,11 +88,52 @@ function Makie.plot!(plt::TreePlot) linewidth = plt.linewidth, Makie.shared_attributes(plt, Makie.Lines)..., ) +end + +# treelabels ================================================================================== +Makie.@recipe(TreeLabels, tree) do scene + attr = Makie.Attributes( + showroot = false, + layoutstyle = :dendrogram, + branchstyle = :square, + openangle = 0, + usemaxdepth = false, + tipannotations = nothing, + tipfontsize = 9.0f0, + tipalign = @something(Makie.theme(scene, :align), (:left, :center)), + tipannotationoffset = @something(Makie.theme(scene, :offset), (3.0f0, 0.0f0)), + ) + Makie.MakieCore.generic_plot_attributes!(attr) + return Makie.MakieCore.colormap_attributes!(attr, Makie.theme(scene, :colormap)) +end + +function Makie.plot!(plt::TreeLabels) + nleaves = BasicTreePlots.leafcount(plt.tree[]) + toangle(y) = (y / (nleaves)) * (2π - (plt.openangle[] % 2pi)) + + ## Setup tree layout + nodecoords = BasicTreePlots.nodepositions( + plt.tree[]; + showroot = plt.showroot[], + layoutstyle = plt.layoutstyle[], + ) + maxleafposition = argmax(x -> x[1], values(nodecoords)) ## Get all tip positions and labels - tippositions_start, tiplabels = BasicTreePlots.tipannotations(nodecoords) + if isnothing(plt.tipannotations[]) + tippositions_start, tiplabels = BasicTreePlots.tipannotations(nodecoords) + else + tiplabels = [] + tippositions_start = Tuple{Float32,Float32}[] + for (nodeid, label) in plt.tipannotations[] + push!(tiplabels, label) + push!(tippositions_start, nodecoords[nodeid]) + end + end ## Lines from each tip to max tip depth + # FIXME: If set to true, it works. Otherwise it raises a StackOverflow error + # It seems to have problems resizing the canvas whenever we add the tip labels. if plt.usemaxdepth[] tippositions_end = Point2f[] for pos in tippositions_start @@ -111,38 +156,260 @@ function Makie.plot!(plt::TreePlot) end end - Makie.lines!(plt, linestomaxdepth; color = (:grey, 0.1), linewidth = 0.5) + Makie.lines!( + plt, + linestomaxdepth; + color = (:gray, 0.5), + linestyle = :dash, + linewidth = 0.5, + ) end - ## Handle tip annotations - if plt.tipannotationsvisible[] - tippositions = plt.usemaxdepth[] ? tippositions_end : tippositions_start - tiprotations = zeros(length(tiplabels)) - if occursin("Polar", string(plt.transformation.transform_func[])) + tippositions = plt.usemaxdepth[] ? tippositions_end : tippositions_start + tiprotations = zeros(length(tiplabels)) + if occursin("Polar", string(plt.transformation.transform_func[])) + tiprotations = map(tippositions) do pos + toangle(pos[2]) + end + tippositions = map(tippositions) do pos + Point2f(toangle(pos[2]), pos[1]) + end + plt.tipannotationoffset[] = (0.0f0, 0.0f0) + end - tiprotations = map(tippositions) do pos - toangle(pos[2]) - end + Makie.text!( + tippositions; + text = tiplabels, + fontsize = plt.tipfontsize, + align = plt.tipalign, + offset = plt.tipannotationoffset, + rotation = tiprotations, + Makie.shared_attributes(plt, Makie.Text)..., + ) +end - tippositions = map(tippositions) do pos - Point2f(toangle(pos[2]), pos[1]) - end - plt.tipannotationoffset[] = (0.0f0, 0.0f0) + +# treescatter ================================================================================= +# TODO: add argument that maps value to colormap or size +Makie.@recipe(TreeScatter, tree) do scene + attr = Makie.Attributes( + alpha = @something(Makie.theme(scene, :alpha), 1.0), + showroot = false, + layoutstyle = :dendrogram, + marker = @something(Makie.theme(scene, :marker), :circle), + markercolor = @something(Makie.theme(scene, :color), :black), + markersize = @something(Makie.theme(scene, :markersize), 5), + nodeordering = AbstractTrees.PreOrderDFS, + openangle = 0, + ) + Makie.MakieCore.generic_plot_attributes!(attr) + return Makie.MakieCore.colormap_attributes!(attr, Makie.theme(scene, :colormap)) +end + +function Makie.plot!(plt::TreeScatter) + nleaves = BasicTreePlots.leafcount(plt.tree[]) + toangle(y) = (y / (nleaves)) * (2π - (plt.openangle[] % 2pi)) + + ## Setup tree layout + nodecoords = BasicTreePlots.nodepositions( + plt.tree[]; + showroot = plt.showroot[], + layoutstyle = plt.layoutstyle[], + ) + + ## Transform coordinate if plotting in Polar Axis + if occursin("Polar", string(plt.transformation.transform_func[])) + nodecoords = Dict(node => (toangle(y), x) for (node, (x, y)) in nodecoords) + end + + ## Add markers in nodes + Makie.scatter!( + plt, + [nodecoords[node] for node in plt.nodeordering[](plt.tree[])], + alpha = plt.alpha[], + marker = plt.marker[], + markersize = plt.markersize[], + color = plt.markercolor[], + colormap = plt.colormap[]; + ) +end + + +# treecladelabel ============================================================================== +Makie.@recipe(TreeCladeLabel, tree) do scene + attr = Makie.Attributes( + node = nothing, + label = nothing, + linepadding = 0.1, + lineoffset = 0.5, + linestyle = @something(Makie.theme(scene, :linestyle), :solid), + linewidth = @something(Makie.theme(scene, :linewidth), 1), + labelalign = @something(Makie.theme(scene, :align), (:left, :center)), + labelrotation = @something(Makie.theme(scene, :rotation), 0.0), + labeloffset = @something(Makie.theme(scene, :offset), (5.0f0, 0.0f0)), + showroot = false, + layoutstyle = :dendrogram, + openangle = 0, + resolution = 25, + alpha = @something(Makie.theme(scene, :alpha), 1.0), + color = @something(Makie.theme(scene, :color), :black), + ) + Makie.MakieCore.generic_plot_attributes!(attr) + return Makie.MakieCore.colormap_attributes!(attr, Makie.theme(scene, :colormap)) +end + +function Makie.plot!(plt::TreeCladeLabel) + nleaves = BasicTreePlots.leafcount(plt.tree[]) + toangle(y) = (y / (nleaves)) * (2π - (plt.openangle[] % 2pi)) + + ## Setup tree layout + nodecoords = BasicTreePlots.nodepositions( + plt.tree[]; + showroot = plt.showroot[], + layoutstyle = plt.layoutstyle[], + ) + + ## Default to labeling whole tree using tiplabels + plt.node[] = isnothing(plt.node[]) ? plt.tree[] : plt.node[] + plt.label[] = isnothing(plt.label[]) ? repr(plt.node[]) : plt.label[] + + ## Get coordinates + x = first(nodecoords[argmax(n -> first(nodecoords[n]), PreOrderDFS(plt.node[]))]) + ymin = last(nodecoords[argmin(n -> last(nodecoords[n]), PreOrderDFS(plt.node[]))]) + ymax = last(nodecoords[argmax(n -> last(nodecoords[n]), PreOrderDFS(plt.node[]))]) + + linecoordinates = [ + (x + plt.lineoffset[], ymin - plt.linepadding[]), + [ + (x + plt.lineoffset[], y) for y in range( + ymin - plt.linepadding[], + ymax + plt.linepadding[], + length = plt.resolution[], + ) + ]..., + (x + plt.lineoffset[], ymax + plt.linepadding[]), + (NaN, NaN), + ] + labelposition = (x + plt.lineoffset[], ymin + ((ymax - ymin) / 2)) + + ## Transform coordinate if plotting in Polar Axis + if occursin("Polar", string(plt.transformation.transform_func[])) + #TODO: Implement for PolarAxis + # error("Not implemented yet...") + linecoordinates = map(linecoordinates) do xy + (toangle(xy[2]), xy[1]) end + labelposition = (toangle(labelposition[2]), labelposition[1]) + plt.labelrotation[] = labelposition[1] + end - Makie.text!( - tippositions; - text = tiplabels, - fontsize = plt.tipfontsize, - align = plt.tipalign, - offset = plt.tipannotationoffset, - rotation = tiprotations, - Makie.shared_attributes(plt, Makie.Text)..., - ) + Makie.lines!( + plt, + linecoordinates, + color = (plt.color[], plt.alpha[]), + linewidth = plt.linewidth, + linestyle = plt.linestyle, + ) + + Makie.text!( + plt, + labelposition; + text = plt.label, + offset = plt.labeloffset, + align = plt.labelalign, + rotation = plt.labelrotation, + color = (plt.color[], plt.alpha[]), + Makie.shared_attributes(plt, Makie.Text)..., + ) +end + +# treearea ==================================================================================== +Makie.@recipe(TreeArea, tree) do scene + attr = Makie.Attributes( + node = nothing, + # Tree + showroot = false, + layoutstyle = :dendrogram, + openangle = 0, + # Fill + alpha = @something(Makie.theme(scene, :alpha), 1.0), + color = @something(Makie.theme(scene, :color), :transparent), + padding = (0.2f0, 0.2f0), + # Stroke + addstroke = false, + strokestyle = @something(Makie.theme(scene, :linestyle), :solid), + strokecolor = @something(Makie.theme(scene, :color), (:black, 1.0)), + strokewidth = @something(Makie.theme(scene, :linewidth), 1.0), + ) + Makie.MakieCore.generic_plot_attributes!(attr) + return Makie.MakieCore.colormap_attributes!(attr, Makie.theme(scene, :colormap)) +end + +function Makie.plot!(plt::TreeArea) + nleaves = BasicTreePlots.leafcount(plt.tree[]) + toangle(y) = (y / (nleaves)) * (2π - (plt.openangle[] % 2pi)) + + ## Setup tree layout + nodecoords = BasicTreePlots.nodepositions( + plt.tree[]; + showroot = plt.showroot[], + layoutstyle = plt.layoutstyle[], + ) + + ## Default to adding area to whole tree + if isnothing(plt.node[]) + plt.node[] = plt.tree[] + end + ## Ensure alpha is applied + if plt.color[] isa Tuple{Any,AbstractFloat} + plt.color[], plt.alpha[] = (plt.color[][1], plt.color[][2] * plt.alpha[]) + end + + ## Transform coordinate if plotting in Polar Axis + if occursin("Polar", string(plt.transformation.transform_func[])) + # TODO: Implement for PolarAxis + error("Not implemented yet...") + else + # Get bounding box coordinates + # FIX: instead of getting list of nodes to traverse, directly extract coordinates to + # simplify the calculation of extrema values + allnodes = PreOrderDFS(plt.node[]) + xmin = + first(nodecoords[argmin(n -> first(nodecoords[n]), allnodes)]) - + plt.padding[][1] + xmax = + first(nodecoords[argmax(n -> first(nodecoords[n]), allnodes)]) + + plt.padding[][1] + ymin = + last(nodecoords[argmin(n -> last(nodecoords[n]), allnodes)]) - plt.padding[][2] + ymax = + last(nodecoords[argmax(n -> last(nodecoords[n]), allnodes)]) + plt.padding[][2] + + # FIX: Do this in a more intelligent way + if plt.addstroke[] + Makie.poly!( + plt, + Point2f[(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)], + color = (plt.color[], plt.alpha[]), + linestyle = plt.strokestyle[], + strokecolor = plt.strokecolor[], + strokewidth = plt.strokewidth[], + ) + else + Makie.poly!( + plt, + Point2f[(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)], + color = (plt.color[], plt.alpha[]), + ) + end end end + + +# themes ====================================================================================== +# TODO: Will this be exposed eventually? theme_empty() = Makie.Theme( Axis = (; topspinevisible = false, diff --git a/src/BasicTreePlots.jl b/src/BasicTreePlots.jl index 223d7fe..94f9492 100644 --- a/src/BasicTreePlots.jl +++ b/src/BasicTreePlots.jl @@ -8,7 +8,16 @@ using AbstractTrees: nodevalue, children, PreOrderDFS const LAYOUTS = (:dendrogram, :cladogram, :radial) const BRANCHTYPES = (:square, :straight) -export treeplot, treeplot! +export treeplot, + treeplot!, + treescatter, + treescatter!, + treelabels, + treelabels!, + treearea, + treearea!, + treecladelabel, + treecladelabel! """ treeplot(tree; kwargs...) @@ -68,6 +77,95 @@ export treeplot, treeplot! function treeplot end function treeplot! end + +""" + treescatter(tree, kwargs...) + +# Args: + +- tree, the root node of a tree that has `AbstractTrees.children()` defined. + All nodes should be reachable by using `AbstractTrees.PreOrderDFS()` iterator. + +# Keyword arguments: + +- `alpha::AbstractFloat = 1.0`, the alpha value of the colormap or color attribute. Multiple alphas like in `treescatter(alpha=0.2, color=(:red, 0.5))`, will get multiplied. + +- `showroot::Bool = false`, if `BasicTreePlots.distance()` is not `nan` for root, show line linking root to parent. + +- `layoutstyle::Symbol = :dendrogram` available options are `:dendrogram`, or `:cladogram` + - `:dendrogram` displays tree taking into account the distance between parent and children nodes as calculated from `BasicTreePlots.distance(node)`. + If the distance is not defined, it defaults to `1` and is equivalent to the `:cladogram` layout + - `:cladogram` displays the tree where each distance from a child node to their parent is set to `1`. + +- `marker::Symbol = :circle`, sets the scatter marker shape. + +- `markercolor = :black`, sets the scatter marker color. + +- `markersize = 5`, sets the scatter marker size. + +- `nodeordering = AbstractTrees.PreOrderDFS`, function that informs algorithm which is the ordering of attributes + `marker`, `markercolor`, and `markersize`. + +- `openangle = 0`, Angle in radians that limits span of tree around the circle when plotted on `PolarAxis`. + if `openangle = deg2rad(5)` then leaf tips will spread across angles `0` to `(2π - openangle)`. + + +""" +function treescatter end +function treescatter! end + + +""" + treelabels(tree, kwargs...) + +# Arguments: + +- `tree`, the root node of a tree that has `AbstractTrees.children()` defined. + All nodes should be reachable by using `AbstractTrees.PreOrderDFS()` iterator. + +# Keyword arguments: + +- `showroot::Bool = false`, if `BasicTreePlots.distance()` is not `nan` for root, show line linking root to parent. + +- `layoutstyle::Symbol = :dendrogram` available options are `:dendrogram`, or `:cladogram` + - `:dendrogram` displays tree taking into account the distance between parent and children nodes as calculated from `BasicTreePlots.distance(node)`. + If the distance is not defined, it defaults to `1` and is equivalent to the `:cladogram` layout + - `:cladogram` displays the tree where each distance from a child node to their parent is set to `1`. + +- `branchstyle::Symbol = :square` available options are `:square` or `:straight` + - `:square` will display line from child to parent as going back to the height of the parent, + before connecting back to the parent node at a right angle. + - `straight` will display line from child to parent as a straight line from child to parent. + +- `tipannotations::{Union{Dict,Nothing}} = nothing`, + +- `usemaxdepth = false`, if `true` draw guide lines from each leaf tip to the depth of the leaf that is maximally distant from root. + Useful for connecting leaves to there location on the y axis (or θ axis if plotted on `PolarAxis`). + +- `tipfontsize = 9.0f0`, font size that tip labels are displayed at. + +- `openangle = 0`, Angle in radians that limits span of tree around the circle when plotted on `PolarAxis`. + if `openangle = deg2rad(5)` then leaf tips will spread across angles `0` to `(2π - openangle)`. + +- `tipalign = (:left, :center)` text alignment of tip labels. + see [Makie options](https://docs.makie.org/v0.21/reference/plots/text#alignment) + +- `tipannotationoffset = (3.0f0, 0.0f0)` offset of tip label from actual tip position. + The first value is associated with the `x` axis, and the second is associated with the `y` axis. + (Currently, only available for cartisian axis) + +""" +function treelabels end +function treelabels! end + + +function treecladelabel end +function treecladelabel! end + + +function treearea end +function treearea! end + # public distance, label """