Skip to content

Commit

Permalink
Add html pretty printing for ArcDiagrams (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens authored Oct 18, 2024
1 parent 2060968 commit e7a3cb1
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ docs/build
db

# jupyter artifacts
*.ipynb
.ipynb_checkpoints

# julia project Manifests
Expand Down
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ version = "0.4.0-DEV"

[deps]
Oscar = "f1435218-dba5-11e9-1e4d-f1a5fab5fc13"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"

[compat]
Oscar = "~1.0.3, ~1.1"
Preferences = "1.4"
julia = "1.8"
38 changes: 13 additions & 25 deletions src/ArcDiagram.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ function vertex_index(p::ArcDiagramVertex)
return p[2]
end

function _vertex_lt(v1::ArcDiagramVertex, v2::ArcDiagramVertex)
if is_upper_vertex(v1) && is_lower_vertex(v2)
return true
elseif is_lower_vertex(v1) && is_upper_vertex(v2)
return false
else
return vertex_index(v1) < vertex_index(v2)
end
end

function is_crossing_free(a::ArcDiagram; part=:everything::Symbol)
if part == :everything
Expand Down Expand Up @@ -182,23 +191,13 @@ function Base.show(io::IO, ::MIME"text/plain", a::ArcDiagramUndirected)
return
end
symb_dict = Dict(v => s for (v, s) in zip(vertices(a), symbols))
function first_vertex(v1::ArcDiagramVertex, v2::ArcDiagramVertex)
if is_upper_vertex(v1) && is_lower_vertex(v2)
return v1
elseif is_lower_vertex(v1) && is_upper_vertex(v2)
return v2
else
return vertex_index(v1) <= vertex_index(v2) ? v1 : v2

end
end
print(io, join(symb_dict[first_vertex(v, neighbor(a, v))] for v in upper_vertices(a)))
print(io, join(symb_dict[_vertex_lt(v, neighbor(a, v)) ? v : neighbor(a, v)] for v in upper_vertices(a)))
if get(io, :compact, false)
print(io, ",")
else
print(io, "\n")
end
print(io, join(symb_dict[first_vertex(v, neighbor(a, v))] for v in lower_vertices(a)))
print(io, join(symb_dict[_vertex_lt(v, neighbor(a, v)) ? v : neighbor(a, v)] for v in lower_vertices(a)))
end

function n_upper_vertices(a::ArcDiagramUndirected)
Expand Down Expand Up @@ -281,21 +280,10 @@ function Base.show(io::IO, ::MIME"text/plain", a::ArcDiagramDirected)
return
end
symb_dict = Dict(v => (lowercase(s), s) for (v, s) in zip(vertices(a), symbols))
function first_vertex(v1::ArcDiagramVertex, v2::ArcDiagramVertex)
if is_upper_vertex(v1) && is_lower_vertex(v2)
return v1
elseif is_lower_vertex(v1) && is_upper_vertex(v2)
return v2
else
return vertex_index(v1) <= vertex_index(v2) ? v1 : v2

end
end

print(
io,
join(
(a.parity_upper_verts[vertex_index(v)] ? first : last)(symb_dict[first_vertex(v, neighbor(a, v))]) for
(a.parity_upper_verts[vertex_index(v)] ? first : last)(symb_dict[_vertex_lt(v, neighbor(a, v)) ? v : neighbor(a, v)]) for
v in upper_vertices(a)
),
)
Expand All @@ -307,7 +295,7 @@ function Base.show(io::IO, ::MIME"text/plain", a::ArcDiagramDirected)
print(
io,
join(
(!a.parity_lower_verts[vertex_index(v)] ? first : last)(symb_dict[first_vertex(v, neighbor(a, v))]) for
(!a.parity_lower_verts[vertex_index(v)] ? first : last)(symb_dict[_vertex_lt(v, neighbor(a, v)) ? v : neighbor(a, v)]) for
v in lower_vertices(a)
),
)
Expand Down
112 changes: 112 additions & 0 deletions src/Misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,115 @@ function symmetrize(f::FreeAssAlgElem)
end
return g
end

function set_show_colorful_html(value::Bool)
old_value = get_show_colorful_html()
@set_preferences!("show_colorful_html" => value)
return old_value
end

function get_show_colorful_html()
return @load_preference("show_colorful_html", default = false)::Bool
end

Base.show(io::IO, ::MIME"text/html", A::ArcDiagram) = print(io, svg_string(A; colorful=get_show_colorful_html()))

function svg_string_defs(::ArcDiagram)
return ""
end

function svg_string_defs(::ArcDiagramDirected)
# marker to be used as an arrowhead
return """
<marker id=\"arrow\" refX=\"2\" refY=\"2\" markerWidth=\"3\" markerHeight=\"4\" orient=\"auto\">
<path d=\"M 0 0 V 4 L 2 2 Z\" stroke=\"context-stroke\" fill=\"context-stroke\"/>
</marker>
"""
end

function svg_string_edge_iterator(A::ArcDiagramUndirected)
return ((v, neighbor(A, v)) for v in vertices(A) if _vertex_lt(v, neighbor(A, v)))
end

function svg_string_edge_iterator(A::ArcDiagramDirected)
return ((v, outneighbor(A, v)) for v in vertices(A) if !isnothing(outneighbor(A, v)))
end

function svg_string_path(v::ArcDiagramVertex, nv::ArcDiagramVertex, dims)
(;margin, h, w) = dims
x_v = (vertex_index(v) - 1) * w + margin
x_nv = (vertex_index(nv) - 1) * w + margin
y_v = is_upper_vertex(v) ? margin : h + margin
y_nv = is_upper_vertex(nv) ? margin : h + margin

function y_c(x1, x2)
return (1-exp(-0.15*(1+abs(x1 - x2))))*0.85
end

if is_upper_vertex(v)
if is_upper_vertex(nv)
x_c1 = (8*x_v + 2*x_nv) / 10
y_c1 = y_c(vertex_index(v), vertex_index(nv)) * h + margin
x_c2 = (2*x_v + 8*x_nv) / 10
y_c2 = y_c(vertex_index(v), vertex_index(nv)) * h + margin
return "M $(x_v) $(y_v) C $(x_c1) $(y_c1), $(x_c2) $(y_c2), $(x_nv) $(y_nv)"
else
return "M $(x_v) $(y_v) L $(x_nv) $(y_nv)"
end
else
if is_upper_vertex(nv)
return "M $(x_v) $(y_v) L $(x_nv) $(y_nv)"
else
x_c1 = (8*x_v + 2*x_nv) / 10
y_c1 = (1 - y_c(vertex_index(v), vertex_index(nv))) * h + margin
x_c2 = (2*x_v + 8*x_nv) / 10
y_c2 = (1 - y_c(vertex_index(v), vertex_index(nv))) * h + margin
return "M $(x_v) $(y_v) C $(x_c1) $(y_c1), $(x_c2) $(y_c2), $(x_nv) $(y_nv)"
end
end
end

function svg_string(A::ArcDiagram; colorful=false)
color_mono = "#008"
size = 40
dims = (
rad=0.1*size,
margin=0.2*size,
h=1*size,
w=0.5*size,
stroke_width=2, #px
)

height = dims.h + 2 * dims.margin
width = (max(n_upper_vertices(A), n_lower_vertices(A)) - 1) * dims.w + 2 * dims.margin

svg = "<svg height=\"$(height)\" width=\"$(width)\" style=\"vertical-align:middle;\">"

svg *= "<defs>$(svg_string_defs(A))</defs>"

i = 0
for (v, nv) in svg_string_edge_iterator(A)
color = colorful ? "hsl($(105*i),100%,45%)" : color_mono
svg *= "<path d=\"$(svg_string_path(v, nv, dims))\" fill=\"transparent\" stroke=\"$color\" stroke-width=\"$(dims.stroke_width)px\" $(A isa ArcDiagramDirected ? "marker-end=\"url(#arrow)\"" : "")/>"
i += 1
end

svg *= "</svg>"
return svg
end

function Base.show(io::IO, mime::MIME"text/html", x::Tuple{Int,ArcDiagram})
print(io, "($(first(x)), ")
show(io, mime, x[2])
print(io, ")")
end

function Base.show(io::IO, mime::MIME"text/html", x::Tuple{ArcDiagram,Vararg{ArcDiagram}})
print(io, "<div>(")
show(io, mime, first(x))
for A in Base.tail(x)
print(io, ", ")
show(io, mime, A)
end
print(io, ")</div>")
end
4 changes: 4 additions & 0 deletions src/PBWDeformations.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module PBWDeformations

using Preferences: Preferences, @load_preference, @set_preferences!

using Oscar

using Oscar.AbstractAlgebra: ProductIterator
Expand Down Expand Up @@ -80,6 +82,7 @@ export edges
export exterior_power
export exterior_power_obj
export general_linear_lie_algebra
export get_show_colorful_html
export inneighbor
export inneighbors
export is_crossing_free
Expand All @@ -101,6 +104,7 @@ export neighbors
export outneighbor
export outneighbors
export pbwdeform_eqs
export set_show_colorful_html
export simple_module
export smash_product
export special_linear_lie_algebra
Expand Down

0 comments on commit e7a3cb1

Please sign in to comment.