From 26876df7a688c6f043032bd5f84b02898c74d604 Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Sat, 10 Jul 2021 13:41:03 -0700 Subject: [PATCH] CLEANUP: Remove experimental parsing of DWDs from yFiles graphs. --- src/graphics/Graphics.jl | 2 - src/graphics/YFilesWiringDiagrams.jl | 186 ---------------------- test/graphics/Graphics.jl | 4 - test/graphics/YFilesWiringDiagrams.jl | 32 ---- test/graphics/data/yed_horizontal.graphml | 171 -------------------- test/graphics/data/yed_vertical.graphml | 171 -------------------- 6 files changed, 566 deletions(-) delete mode 100644 src/graphics/YFilesWiringDiagrams.jl delete mode 100644 test/graphics/YFilesWiringDiagrams.jl delete mode 100644 test/graphics/data/yed_horizontal.graphml delete mode 100644 test/graphics/data/yed_vertical.graphml diff --git a/src/graphics/Graphics.jl b/src/graphics/Graphics.jl index 19f7be989..4403b0c36 100644 --- a/src/graphics/Graphics.jl +++ b/src/graphics/Graphics.jl @@ -10,14 +10,12 @@ include("GraphvizWiringDiagrams.jl") include("ComposeWiringDiagrams.jl") include("TikZ.jl") include("TikZWiringDiagrams.jl") -include("YFilesWiringDiagrams.jl") @reexport using .WiringDiagramLayouts @reexport using .GraphvizGraphs @reexport using .GraphvizWiringDiagrams @reexport using .ComposeWiringDiagrams @reexport using .TikZWiringDiagrams -@reexport using .YFilesWiringDiagrams function __init__() @require Convex="f65535da-76fb-5f13-bab9-19810c17039a" begin diff --git a/src/graphics/YFilesWiringDiagrams.jl b/src/graphics/YFilesWiringDiagrams.jl deleted file mode 100644 index 7550826df..000000000 --- a/src/graphics/YFilesWiringDiagrams.jl +++ /dev/null @@ -1,186 +0,0 @@ -""" Deserialize abstract wiring diagram from yFiles. - -Reads a wiring diagram from the GraphML dialect used by yEd and yFiles. Unlike -the GraphML spec, the yEd data model does not explicitly include ports: - -- https://yed.yworks.com/support/qa/102/ -- https://yed.yworks.com/support/qa/2531/ - -We infer the ports of boxes and their order from the geometry of the diagram. -Thus, this module has the nature of a hack. While it may be useful for -interactive and exploratory work, it should not be used in a production system. -""" -module YFilesWiringDiagrams -export read_yfiles_diagram, parse_yfiles_diagram - -using LightXML - -using ...CategoricalAlgebra.CSets: incident -using ...Graphs, ...WiringDiagrams -import ...WiringDiagrams.GraphMLWiringDiagrams: parse_graphml_data_value, - parse_graphml_metagraph -using ..WiringDiagramLayouts: LayoutOrientation, TopToBottom, is_vertical - -# Data types -############ - -struct BoxLayout - box::Int - input_coord_map::Dict # Map from coordinates to input ports - output_coord_map::Dict # Map from coordinates to output ports -end - -# Deserialization -################# - -""" Read a wiring diagram from a GraphML file created by yEd and yFiles. -""" -function read_yfiles_diagram(BoxValue::Type, WireValue::Type, filename::String; kw...) - parse_yfiles_diagram(BoxValue, WireValue, LightXML.parse_file(filename); kw...) -end - -""" Parse a wiring diagram from a GraphML string or XML doc created by yFiles. -""" -function parse_yfiles_diagram(BoxValue::Type, WireValue::Type, s::AbstractString; kw...) - parse_yfiles_diagram(BoxValue, WireValue, LightXML.parse_string(s); kw...) -end -function parse_yfiles_diagram(BoxValue::Type, WireValue::Type, xdoc::XMLDocument; - orientation::LayoutOrientation=TopToBottom, keep_labels::Bool=true)::WiringDiagram - # Clean up GraphML keys before reading. - xroot = root(xdoc) - for xkey in xroot["key"] - yfiles_type = attribute(xkey, "yfiles.type") - if !isnothing(yfiles_type) - if !has_attribute(xkey, "attr.name") - set_attribute(xkey, "attr.name", yfiles_type) - end - if !has_attribute(xkey, "attr.type") - set_attribute(xkey, "attr.type", "yfiles_$yfiles_type") - end - end - end - - # Read the diagram's underlying graph as an attributed graph. - graph = parse_graphml_metagraph(xdoc, directed=true) - - # Extract needed information from yFiles' "nodegraphics" and "edgegraphics" - # and discard the rest. Keep custom data properties, except the blank - # "description" property inserted by yEd. - for v in 1:nv(graph) - v_data = vprops(graph, v) - if haskey(v_data, :description) && isempty(v_data[:description]) - delete!(v_data, :description) - end - node_graphics = pop!(v_data, :nodegraphics) - if keep_labels & haskey(node_graphics, :label) - v_data[:label] = node_graphics[:label] - end - end - for edge in edges(graph) - wire_data = eprops(graph, edge) - if haskey(wire_data, :description) && isempty(wire_data[:description]) - delete!(wire_data, :description) - end - edge_graphics = pop!(wire_data, :edgegraphics) - wire_data[:source_coord] = round(Int, - edge_graphics[is_vertical(orientation) ? :source_x : :source_y]) - wire_data[:target_coord] = round(Int, - edge_graphics[is_vertical(orientation) ? :target_x : :target_y]) - if keep_labels & haskey(edge_graphics, :label) - wire_data[:label] = edge_graphics[:label] - end - end - - # Add boxes and their ports to diagram, including the outer box. - diagram = WiringDiagram([], []) - boxes = BoxLayout[] - for v in 1:nv(graph) - box_layout = if pop!(vprops(graph, v), :input, false) - # Special case: diagram inputs. - ports, coord_map = infer_output_ports(graph, v) - add_input_ports!(diagram, ports) - BoxLayout(input_id(diagram), Dict(), coord_map) - elseif pop!(vprops(graph, v), :output, false) - # Special case: diagram outputs. - ports, coord_map = infer_input_ports(graph, v) - add_output_ports!(diagram, ports) - BoxLayout(output_id(diagram), coord_map, Dict()) - else - # Generic case: a box. - input_ports, input_coord_map = infer_input_ports(graph, v) - output_ports, output_coord_map = infer_output_ports(graph, v) - value = convert_from_graphml_data(BoxValue, vprops(graph, v)) - box_id = add_box!(diagram, Box(value, input_ports, output_ports)) - BoxLayout(box_id, input_coord_map, output_coord_map) - end - push!(boxes, box_layout) - end - - # Add wires to diagram. - for edge in edges(graph) - wire_data = eprops(graph, edge) - source, target = boxes[src(graph, edge)], boxes[tgt(graph, edge)] - source_port = source.output_coord_map[pop!(wire_data, :source_coord)] - target_port = target.input_coord_map[pop!(wire_data, :target_coord)] - value = convert_from_graphml_data(WireValue, wire_data) - add_wire!(diagram, Wire(value, - (source.box, source_port) => (target.box, target_port))) - end - - diagram -end - -function infer_input_ports(graph::PropertyGraph, v::Int) - in_edges = incident(graph.graph, v, :tgt) - in_coords = [ get_eprop(graph, edge, :target_coord) for edge in in_edges ] - infer_ports_from_coordinates(in_coords) -end -function infer_output_ports(graph::PropertyGraph, v::Int) - out_edges = incident(graph.graph, v, :src) - out_coords = [ get_eprop(graph, edge, :source_coord) for edge in out_edges ] - infer_ports_from_coordinates(out_coords) -end - -function infer_ports_from_coordinates(coords::Vector{T}) where T - unique_coords = sort(unique(coords)) - ports = repeat([nothing], length(unique_coords)) - coord_map = Dict{T,Int}(x => i for (i, x) in enumerate(unique_coords)) - (ports, coord_map) -end - -function parse_graphml_data_value(::Type{Val{:yfiles_nodegraphics}}, xdata::XMLElement) - ynode = first(child_elements(xdata)) # e.g., ShapeNode - ygeom = find_element(ynode, "Geometry") - data = Dict{Symbol,Any}( - :x => float_attribute(ygeom, "x"), - :y => float_attribute(ygeom, "y"), - :width => float_attribute(ygeom, "width"), - :height => float_attribute(ygeom, "height"), - ) - ylabel = find_element(ynode, "NodeLabel") - if !isnothing(ylabel) - data[:label] = content(ylabel) - end - data -end - -function parse_graphml_data_value(::Type{Val{:yfiles_edgegraphics}}, xdata::XMLElement) - yedge = first(child_elements(xdata)) # e.g., PolyLineEdge - ypath = find_element(yedge, "Path") - data = Dict{Symbol,Any}( - :source_x => float_attribute(ypath, "sx"), - :source_y => float_attribute(ypath, "sy"), - :target_x => float_attribute(ypath, "tx"), - :target_y => float_attribute(ypath, "ty"), - ) - ylabel = find_element(yedge, "EdgeLabel") - if !isnothing(ylabel) - data[:label] = content(ylabel) - end - data -end - -float_attribute(xelem::XMLElement, name::AbstractString) = - parse(Float64, attribute(xelem, name, required=true)) - -end diff --git a/test/graphics/Graphics.jl b/test/graphics/Graphics.jl index c56668858..839ce58b4 100644 --- a/test/graphics/Graphics.jl +++ b/test/graphics/Graphics.jl @@ -18,7 +18,3 @@ end include("TikZ.jl") include("TikZWiringDiagrams.jl") end - -@testset "yFiles" begin - include("YFilesWiringDiagrams.jl") -end diff --git a/test/graphics/YFilesWiringDiagrams.jl b/test/graphics/YFilesWiringDiagrams.jl deleted file mode 100644 index d6a0e7346..000000000 --- a/test/graphics/YFilesWiringDiagrams.jl +++ /dev/null @@ -1,32 +0,0 @@ -module TestYFilesWiringDiagrams - -using Test -using Catlab.WiringDiagrams, Catlab.Graphics - -function read_yfiles(name::String; kw...) - filename = joinpath(@__DIR__, "data", name) - read_yfiles_diagram(Symbol, Symbol, filename; kw...) -end - -ports(n::Int) = repeat([nothing], n) -d = WiringDiagram(ports(1), ports(1)) -fv = add_box!(d, Box(:f, ports(1), ports(2))) -gv = add_box!(d, Box(:g, ports(2), ports(1))) -hv = add_box!(d, Box(:h, ports(1), ports(1))) -kv = add_box!(d, Box(:k, ports(1), ports(1))) -add_wires!(d, [ - Wire(:A, (input_id(d),1) => (fv, 1)), - Wire(:B, (fv,1) => (hv,1)), Wire(:C, (fv,2) => (kv,1)), - Wire(:D, (hv,1) => (gv,1)), Wire(:E, (kv,1) => (gv,2)), - Wire(:F, (gv,1) => (output_id(d),1)), -]) - -d_vertical = read_yfiles("yed_vertical.graphml", orientation=TopToBottom) -@test nboxes(d_vertical) == nboxes(d) -@test is_isomorphic(d_vertical, d) - -d_horizontal = read_yfiles("yed_horizontal.graphml", orientation=LeftToRight) -@test nboxes(d_horizontal) == nboxes(d) -@test is_isomorphic(d_horizontal, d) - -end diff --git a/test/graphics/data/yed_horizontal.graphml b/test/graphics/data/yed_horizontal.graphml deleted file mode 100644 index b4bbfe868..000000000 --- a/test/graphics/data/yed_horizontal.graphml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - false - - - false - - - - - - - - - - - - - - - - f - - - - - - - - - - - g - - - - - - - - - - - k - - - - - - - - - - - h - - - - - - true - - - - - - in - - - - - - true - - - - - - out - - - - - - - - - - - - - - C - - - - - - - - - - - - - - B - - - - - - - - - - - - - - D - - - - - - - - - - - - - - E - - - - - - - - - - - A - - - - - - - - - - - F - - - - - - - - - diff --git a/test/graphics/data/yed_vertical.graphml b/test/graphics/data/yed_vertical.graphml deleted file mode 100644 index ed1742f13..000000000 --- a/test/graphics/data/yed_vertical.graphml +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - false - - - false - - - - - - - - - - - - - - - - f - - - - - - - - - - - g - - - - - - - - - - - h - - - - - - - - - - - k - - - - - - true - - - - - - in - - - - - - true - - - - - - out - - - - - - - - - - - - - - B - - - - - - - - - - - - - - C - - - - - - - - - - - - - - E - - - - - - - - - - - - - - D - - - - - - - - - - - A - - - - - - - - - - - F - - - - - - - - -