Skip to content

Commit 6a4278a

Browse files
authored
Merge pull request #116 from JuliaRobotics/feature/3Q19/sortDFG
alias for sort dfg symbol lists
2 parents 506905f + 5993c69 commit 6a4278a

File tree

10 files changed

+171
-16
lines changed

10 files changed

+171
-16
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
77
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
88
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
99
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
10+
GraphPlot = "a2cc645c-3eea-5389-862e-a155d0052231"
1011
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1112
JSON2 = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
1213
LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d"

docs/src/func_ref.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ getSubgraphAroundNode
5858
getSubgraph
5959
```
6060

61-
### Visualization
61+
### Visualization and Plotting
6262
```@docs
6363
toDot
6464
toDotFile
65+
dfgplot
6566
```

src/Common.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export sortVarNested
1+
2+
export sortVarNested, sortDFG
23
export isPrior, lsfPriors
34
export getVariableType, getSofttype
45
export getFactorType, getfnctype
@@ -88,6 +89,24 @@ function sortVarNested(vars::Vector{Symbol})::Vector{Symbol}
8889
return retvars
8990
end
9091

92+
"""
93+
$SIGNATURES
94+
95+
Sort variable (factor) lists in a meaningful way, for example `[:april;:x1_3;:x1_6;]`
96+
97+
Notes
98+
- Not fool proof, but does better than native sort.
99+
100+
Example
101+
102+
`sortDFG(ls(dfg))`
103+
104+
Related
105+
106+
ls, lsf
107+
"""
108+
sortDFG(vars::Vector{Symbol})::Vector{Symbol} = sortVarNested(vars)
109+
91110
"""
92111
$SIGNATURES
93112

src/DFGPlots/DFGPlots.jl

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ using Colors
44
using LightGraphs
55
using MetaGraphs
66
using GraphPlot
7+
using DocStringExtensions
78
import GraphPlot: gplot
89

910
using ...DistributedFactorGraphs
@@ -28,6 +29,26 @@ DFGPlotProps() = DFGPlotProps( (var=colorant"seagreen", fac=colorant"cyan3"),
2829
true)
2930

3031

32+
33+
"""
34+
$(SIGNATURES)
35+
Plots the structure of the factor graph. GraphPlot must be imported before DistributedFactoGraphs for these functions to be available.
36+
Returns the plot context.
37+
38+
E.g.
39+
```
40+
using GraphPlot
41+
using DistributedFactorGraphs, DistributedFactorGraphs.DFGPlots
42+
# ... Make graph...
43+
# Using GraphViz plotting
44+
dfgplot(fg)
45+
# Save to PDFG
46+
using Compose
47+
draw(PDF("/tmp/graph.pdf", 16cm, 16cm), dfgplot(fg))
48+
```
49+
50+
More information at [GraphPlot.jl](https://github.com/JuliaGraphs/GraphPlot.jl)
51+
"""
3152
function dfgplot(dfg::LightDFG, p::DFGPlotProps = DFGPlotProps())
3253

3354
nodetypes = [haskey(dfg.g.variables, s) for s in dfg.g.labels]
@@ -46,6 +67,25 @@ function dfgplot(dfg::LightDFG, p::DFGPlotProps = DFGPlotProps())
4667

4768
end
4869

70+
"""
71+
$(SIGNATURES)
72+
Plots the structure of the factor graph. GraphPlot must be imported before DistributedFactoGraphs for these functions to be available.
73+
Returns the plot context.
74+
75+
E.g.
76+
```
77+
using GraphPlot
78+
using DistributedFactorGraphs, DistributedFactorGraphs.DFGPlots
79+
# ... Make graph...
80+
# Using GraphViz plotting
81+
dfgplot(fg)
82+
# Save to PDFG
83+
using Compose
84+
draw(PDF("/tmp/graph.pdf", 16cm, 16cm), dfgplot(fg))
85+
```
86+
87+
More information at [GraphPlot.jl](https://github.com/JuliaGraphs/GraphPlot.jl)
88+
"""
4989
function dfgplot(dfg::MetaGraphsDFG, p::DFGPlotProps = DFGPlotProps())
5090

5191
nodesize = [has_prop(dfg.g,i,:factor) ? p.nodesize.fac : p.nodesize.var for i=vertices(dfg.g)]
@@ -60,14 +100,32 @@ function dfgplot(dfg::MetaGraphsDFG, p::DFGPlotProps = DFGPlotProps())
60100

61101
end
62102

103+
"""
104+
$(SIGNATURES)
105+
Plots the structure of the factor graph. GraphPlot must be imported before DistributedFactoGraphs for these functions to be available.
106+
Returns the plot context.
107+
108+
E.g.
109+
```
110+
using GraphPlot
111+
using DistributedFactorGraphs, DistributedFactorGraphs.DFGPlots
112+
# ... Make graph...
113+
# Using GraphViz plotting
114+
dfgplot(fg)
115+
# Save to PDFG
116+
using Compose
117+
draw(PDF("/tmp/graph.pdf", 16cm, 16cm), dfgplot(fg))
118+
```
119+
120+
More information at [GraphPlot.jl](https://github.com/JuliaGraphs/GraphPlot.jl)
121+
"""
63122
function dfgplot(dfg::AbstractDFG, p::DFGPlotProps = DFGPlotProps())
64123
# TODO implement convert functions
65124
@warn "TODO Implement convert"
66125
ldfg = MetaGraphsDFG{AbstractParams}()
67126
DistributedFactorGraphs._copyIntoGraph!(dfg, ldfg, union(getVariableIds(dfg), getFactorIds(dfg)), true)
68127

69128
dfgplot(ldfg, p)
70-
71129
end
72130

73131
function gplot(dfg::MetaGraphsDFG; keyargs...)

src/DistributedFactorGraphs.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ export pack, unpack
4242
#Interfaces
4343
export getAdjacencyMatrixSparse
4444

45+
# File import and export
46+
export saveDFG, loadDFG
47+
4548
# Common includes
4649
include("services/AbstractDFG.jl")
4750
include("services/DFGVariable.jl")
@@ -61,8 +64,6 @@ include("SymbolDFG/SymbolDFG.jl")
6164
include("LightDFG/LightDFG.jl")
6265
@reexport using .LightDFGs
6366

64-
export saveDFG, loadDFG
65-
6667
function __init__()
6768
@require Neo4j="d2adbeaf-5838-5367-8a2f-e46d570981db" begin
6869
# Include the Cloudgraphs API

src/entities/DFGFactor.jl

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# Originally from IncrementalInference
32

43
abstract type InferenceType end
@@ -48,18 +47,37 @@ mutable struct DFGFactor{T, S} <: DFGNode
4847
end
4948

5049
label(f::F) where F <: DFGFactor = f.label
51-
data(f::F) where F <: DFGFactor = f.data
50+
"""
51+
$SIGNATURES
52+
53+
Retrieve solver data structure stored in a factor.
54+
"""
55+
function solverData(f::F) where F <: DFGFactor
56+
return f.data
57+
end
58+
"""
59+
$SIGNATURES
60+
61+
Retrieve solver data structure stored in a factor.
62+
"""
63+
function data(f::DFGFactor)::GenericFunctionNodeData
64+
@warn "data() is deprecated, please use solverData()"
65+
return f.data
66+
end
67+
"""
68+
$SIGNATURES
69+
70+
Retrieve solver data structure stored in a factor.
71+
"""
72+
function getData(f::DFGFactor)::GenericFunctionNodeData
73+
@warn "getData is deprecated, please use solverData()"
74+
return f.data
75+
end
76+
5277
internalId(f::F) where F <: DFGFactor = f._internalId
5378

5479
# Simply for convenience - don't export
5580
const PackedFunctionNodeData{T} = GenericFunctionNodeData{T, <: AbstractString}
5681
PackedFunctionNodeData(x1, x2, x3, x4, x5::S, x6::T, x7::String="", x8::Vector{Int}=Int[]) where {T <: PackedInferenceType, S <: AbstractString} = GenericFunctionNodeData(x1, x2, x3, x4, x5, x6, x7, x8)
5782
const FunctionNodeData{T} = GenericFunctionNodeData{T, Symbol}
5883
FunctionNodeData(x1, x2, x3, x4, x5::Symbol, x6::T, x7::String="", x8::Vector{Int}=Int[]) where {T <: Union{FunctorInferenceType, ConvolutionObject}}= GenericFunctionNodeData{T, Symbol}(x1, x2, x3, x4, x5, x6, x7, x8)
59-
60-
"""
61-
$SIGNATURES
62-
63-
Retrieve data structure stored in a node.
64-
"""
65-
getData(v::DFGFactor)::GenericFunctionNodeData = v.data

src/entities/DFGVariable.jl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,26 @@ timestamp(v::DFGVariable) = v.timestamp
104104
tags(v::DFGVariable) = v.tags
105105
estimates(v::DFGVariable) = v.estimateDict
106106
estimate(v::DFGVariable, key::Symbol=:default) = haskey(v.estimateDict, key) ? v.estimateDict[key] : nothing
107+
"""
108+
$SIGNATURES
109+
110+
Retrieve solver data structure stored in a variable.
111+
"""
107112
solverData(v::DFGVariable, key::Symbol=:default) = haskey(v.solverDataDict, key) ? v.solverDataDict[key] : nothing
108-
getData(v::DFGVariable; solveKey::Symbol=:default)::VariableNodeData = v.solverDataDict[solveKey]
113+
"""
114+
$SIGNATURES
115+
116+
Retrieve data structure stored in a variable.
117+
"""
118+
function getData(v::DFGVariable; solveKey::Symbol=:default)::VariableNodeData
119+
@warn "getData is deprecated, please use solverData()"
120+
return v.solverDataDict[solveKey]
121+
end
122+
"""
123+
$SIGNATURES
124+
125+
Set solver data structure stored in a variable.
126+
"""
109127
setSolverData(v::DFGVariable, data::VariableNodeData, key::Symbol=:default) = v.solverDataDict[key] = data
110128
solverDataDict(v::DFGVariable) = v.solverDataDict
111129
internalId(v::DFGVariable) = v._internalId

test/interfaceTests.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ end
4747
@test getFactorIds(dfg) == [:f1]
4848
#
4949
@test lsf(dfg, :a) == [f1.label]
50-
#tags
50+
# Tags
5151
@test ls(dfg, tags=[:POSE]) == [:a]
5252
@test symdiff(ls(dfg, tags=[:POSE, :LANDMARK]), ls(dfg, tags=[:VARIABLE])) == []
5353
# Regexes
@@ -61,6 +61,11 @@ end
6161
@test exists(dfg, :a) == true
6262
@test exists(dfg, v1) == true
6363
@test exists(dfg, :nope) == false
64+
# Sorting of results
65+
# TODO - this function needs to be cleaned up
66+
unsorted = [:x1_3;:x1_6;:l1;:april1] #this will not work for :x1x2f1
67+
@test sortDFG(unsorted) == sortVarNested(unsorted)
68+
@test_skip sortDFG([:x1x2f1, :x1l1f1]) == [:x1l1f1, :x1x2f1]
6469
end
6570

6671
# Gets
@@ -85,12 +90,17 @@ end
8590
@test estimates(v1) == v1.estimateDict
8691
@test estimate(v1, :notfound) == nothing
8792
@test solverData(v1) === v1.solverDataDict[:default]
93+
@test getData(v1) === v1.solverDataDict[:default]
8894
@test solverData(v1, :default) === v1.solverDataDict[:default]
8995
@test solverDataDict(v1) == v1.solverDataDict
9096
@test internalId(v1) == v1._internalId
9197

9298
@test label(f1) == f1.label
99+
@test solverData(f1) == f1.data
100+
# Deprecated functions
93101
@test data(f1) == f1.data
102+
@test getData(f1) == f1.data
103+
# Internal function
94104
@test internalId(f1) == f1._internalId
95105

96106
@test getSolverParams(dfg) != nothing

test/plottingTest.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# using GraphPlot
2+
using DistributedFactorGraphs
3+
using DistributedFactorGraphs.DFGPlots
4+
using Test
5+
6+
# Now make a complex graph for connectivity tests
7+
numNodes = 10
8+
dfg = GraphsDFG{NoSolverParams}()
9+
verts = map(n -> DFGVariable(Symbol("x$n")), 1:numNodes)
10+
#change ready and backendset for x7,x8 for improved tests on x7x8f1
11+
verts[7].ready = 1
12+
verts[8].backendset = 1
13+
map(v -> addVariable!(dfg, v), verts)
14+
map(n -> addFactor!(dfg, [verts[n], verts[n+1]], DFGFactor{Int, :Symbol}(Symbol("x$(n)x$(n+1)f1"))), 1:(numNodes-1))
15+
16+
# Using toDot
17+
dot = toDot(dfg)
18+
@test dot != nothing
19+
20+
# Using GraphViz plotting
21+
plot = dfgplot(dfg)
22+
@test plot != nothing

test/runtests.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Test
2+
using GraphPlot # For plotting tests
23
using DistributedFactorGraphs
34

45
# Test each interface
@@ -9,3 +10,9 @@ for api in apis
910
include("interfaceTests.jl")
1011
end
1112
end
13+
14+
# Test special cases
15+
16+
@testset "Plotting Tests" begin
17+
include("plottingTest.jl")
18+
end

0 commit comments

Comments
 (0)