Skip to content

Commit c3e58d3

Browse files
authored
Merge pull request #88 from JuliaRobotics/jt/develop
Integrating @Affie's changes into master (v0.4 release)
2 parents da4eff0 + cb93bf5 commit c3e58d3

File tree

24 files changed

+2215
-111
lines changed

24 files changed

+2215
-111
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
deps/deps.jl
55
docs/build
66
Manifest.toml
7+
dev

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
name = "DistributedFactorGraphs"
22
uuid = "b5cc3c7e-6572-11e9-2517-99fb8daf2f04"
3-
version = "0.3.2"
3+
version = "0.4.0"
44

55
[deps]
6+
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
67
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
78
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
89
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
@@ -15,15 +16,16 @@ MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5"
1516
Neo4j = "d2adbeaf-5838-5367-8a2f-e46d570981db"
1617
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1718
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
19+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1820

1921
[compat]
2022
Distributions = "≥ 0.18"
2123
DocStringExtensions = "≥ 0.7"
2224
Graphs = "≥ 0.10.3"
25+
MetaGraphs = "≥ 0.6.4"
2326
Reexport = "≥ 0.2"
2427
Requires = "≥ 0.5"
2528
julia = "0.7, 1"
26-
MetaGraphs = "≥ 0.6.4"
2729

2830
[extras]
2931
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

src/CloudGraphsDFG/services/CloudGraphsDFG.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ Optionally provide a distance to specify the number of edges should be followed.
704704
Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created.
705705
Note: By default orphaned factors (where the subgraph does not contain all the related variables) are not returned. Set includeOrphanFactors to return the orphans irrespective of whether the subgraph contains all the variables.
706706
"""
707-
function getSubgraphAroundNode(dfg::CloudGraphsDFG, node::T, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::Union{Nothing, CloudGraphsDFG}=nothing)::CloudGraphsDFG where T <: DFGNode
707+
function getSubgraphAroundNode(dfg::CloudGraphsDFG, node::DFGNode, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::Union{Nothing, CloudGraphsDFG}=nothing)::CloudGraphsDFG
708708
distance < 1 && error("getSubgraphAroundNode() only works for distance > 0")
709709

710710
# Making a copy session if not specified
@@ -720,6 +720,19 @@ function getSubgraphAroundNode(dfg::CloudGraphsDFG, node::T, distance::Int64=1,
720720
return addToDFG
721721
end
722722

723+
function getSubgraphAroundNode(dfg::CloudGraphsDFG{<:AbstractParams}, node::DFGNode, distance::Int64, includeOrphanFactors::Bool, addToDFG::MetaGraphsDFG{AbstractParams})::AbstractDFG
724+
distance < 1 && error("getSubgraphAroundNode() only works for distance > 0")
725+
726+
727+
# Thank you Neo4j for 0..* awesomeness!!
728+
neighborList = _getLabelsFromCyphonQuery(dfg.neo4jInstance, "(n:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId):$(node.label))-[FACTORGRAPH*0..$distance]-(node:$(dfg.userId):$(dfg.robotId):$(dfg.sessionId))")
729+
730+
# Copy the section of graph we want
731+
_copyIntoGraph!(dfg, addToDFG, neighborList, includeOrphanFactors)
732+
return addToDFG
733+
end
734+
735+
723736
"""
724737
$(SIGNATURES)
725738
Get a deep subgraph copy from the DFG given a list of variables and factors.

src/Common.jl

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export getData
55
export getVariableType, getSofttype
66
export getFactorType, getfnctype
77
export lsTypes, lsfTypes
8-
8+
export lsWho, lsfWho
99

1010
"""
1111
$(SIGNATURES)
@@ -230,3 +230,35 @@ function lsTypes(dfg::G)::Dict{Symbol, Vector{String}} where G <: AbstractDFG
230230
end
231231
return alltypes
232232
end
233+
234+
235+
"""
236+
$(SIGNATURES)
237+
Gives back all factor labels that fit the bill:
238+
lsWho(dfg, :Pose3)
239+
"""
240+
function lsWho(dfg::AbstractDFG, type::Symbol; solveKey::Symbol=:default)::Vector{Symbol}
241+
vars = getVariables(dfg)
242+
labels = Symbol[]
243+
for v in vars
244+
varType = typeof(getVariableType(v, solveKey=solveKey)).name |> Symbol
245+
varType == type && push!(labels, v.label)
246+
end
247+
return labels
248+
end
249+
250+
251+
"""
252+
$(SIGNATURES)
253+
Gives back all factor labels that fit the bill:
254+
lsfWho(dfg, :Point2Point2)
255+
"""
256+
function lsfWho(dfg::AbstractDFG, type::Symbol)::Vector{Symbol}
257+
facs = getFactors(dfg)
258+
labels = Symbol[]
259+
for f in facs
260+
facType = typeof(getFactorType(f)).name |> Symbol
261+
facType == type && push!(labels, f.label)
262+
end
263+
return labels
264+
end

src/DFGPlots/DFGPlots.jl

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,58 @@ end
2424
DFGPlotProps() = DFGPlotProps( (var=colorant"seagreen", fac=colorant"cyan3"),
2525
(var=1.0, fac=0.3),
2626
(var=:box, fac=:elipse),
27-
spring_layout,
27+
spectral_layout,
2828
true)
2929

3030

31-
function dfgplot(dfg::LightGraphsDFG)
31+
function dfgplot(dfg::LightDFG, p::DFGPlotProps = DFGPlotProps())
3232

33-
nodesize = [has_prop(dfg.g,i,:factor) ? 0.3 : 1.0 for i=vertices(dfg.g)]
34-
nodelabel = [has_prop(dfg.g,i,:factor) ? "" : string(get_prop(dfg.g,i,:label)) for i=vertices(dfg.g)]
35-
nodefillc = [has_prop(dfg.g,i,:factor) ? colorant"seagreen" : colorant"cyan3" for i=vertices(dfg.g)]
33+
nodetypes = [haskey(dfg.g.variables, s) for s in dfg.g.labels]
3634

37-
gplot(dfg.g, nodelabel=nodelabel, nodesize=nodesize, nodefillc=nodefillc, layout=spectral_layout)
35+
nodesize = [isVar ? p.nodesize.var : p.nodesize.fac for isVar in nodetypes]
36+
# nodelabel = [isVar ? string(get_prop(dfg.g,i,:label)) : "" for (i,isVar) in enumerate(nodetypes)]
37+
if p.drawlabels
38+
nodelabel = [nodetypes[i] ? string(s) : "" for (i,s) in enumerate(dfg.g.labels)]
39+
else
40+
nodelabel = nothing
41+
end
42+
43+
nodefillc = [isVar ? p.nodefillc.var : p.nodefillc.fac for isVar in nodetypes]
44+
45+
gplot(dfg.g, nodelabel=nodelabel, nodesize=nodesize, nodefillc=nodefillc, layout=p.layout)
3846

3947
end
4048

41-
function gplot(dfg::LightGraphsDFG; keyargs...)
42-
gplot(dfg.g; keyargs...)
49+
function dfgplot(dfg::MetaGraphsDFG, p::DFGPlotProps = DFGPlotProps())
50+
51+
nodesize = [has_prop(dfg.g,i,:factor) ? p.nodesize.fac : p.nodesize.var for i=vertices(dfg.g)]
52+
if p.drawlabels
53+
nodelabel = [has_prop(dfg.g,i,:factor) ? "" : string(get_prop(dfg.g,i,:label)) for i=vertices(dfg.g)]
54+
else
55+
nodelabel = nothing
56+
end
57+
nodefillc = [has_prop(dfg.g,i,:factor) ? p.nodefillc.fac : p.nodefillc.var for i=vertices(dfg.g)]
58+
59+
gplot(dfg.g, nodelabel=nodelabel, nodesize=nodesize, nodefillc=nodefillc, layout=p.layout)
60+
4361
end
4462

45-
function dfgplot(dfg::AbstractDFG)
63+
function dfgplot(dfg::AbstractDFG, p::DFGPlotProps = DFGPlotProps())
4664
# TODO implement convert functions
4765
@warn "TODO Implement convert"
48-
ldfg = LightGraphsDFG{AbstractParams}()
66+
ldfg = MetaGraphsDFG{AbstractParams}()
4967
DistributedFactorGraphs._copyIntoGraph!(dfg, ldfg, union(getVariableIds(dfg), getFactorIds(dfg)), true)
5068

51-
nodesize = [has_prop(ldfg.g,i,:factor) ? 0.3 : 1.0 for i=vertices(ldfg.g)]
52-
nodelabel = [has_prop(ldfg.g,i,:factor) ? "" : string(get_prop(ldfg.g,i,:label)) for i=vertices(ldfg.g)]
53-
nodefillc = [has_prop(ldfg.g,i,:factor) ? colorant"seagreen" : colorant"cyan3" for i=vertices(ldfg.g)]
69+
dfgplot(ldfg, p)
5470

55-
gplot(ldfg.g, nodelabel=nodelabel, nodesize=nodesize, nodefillc=nodefillc, layout=spectral_layout)
71+
end
5672

73+
function gplot(dfg::MetaGraphsDFG; keyargs...)
74+
gplot(dfg.g; keyargs...)
75+
end
76+
77+
function gplot(dfg::LightDFG; keyargs...)
78+
gplot(dfg.g; keyargs...)
5779
end
5880

5981
end

src/DistributedFactorGraphs.jl

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using Distributions
88
using Reexport
99
using JSON2
1010
using LinearAlgebra
11+
using SparseArrays
1112

1213
# Entities
1314
include("entities/AbstractTypes.jl")
@@ -34,6 +35,9 @@ export GenericFunctionNodeData#, FunctionNodeData
3435
export getSerializationModule, setSerializationModule!
3536
export pack, unpack
3637

38+
#Interfaces
39+
export getAdjacencyMatrixSparse
40+
3741
# Common includes
3842
include("services/AbstractDFG.jl")
3943
include("services/DFGVariable.jl")
@@ -45,7 +49,13 @@ include("GraphsDFG/GraphsDFG.jl")
4549
include("FileDFG/FileDFG.jl")
4650

4751
# Include the LightGraphs.jl (MetaGraphs.jl) API.
48-
include("LightGraphsDFG/LightGraphsDFG.jl")
52+
include("MetaGraphsDFG/MetaGraphsDFG.jl")
53+
54+
include("SymbolDFG/SymbolDFG.jl")
55+
@reexport using .SymbolDFGs
56+
57+
include("LightDFG/LightDFG.jl")
58+
@reexport using .LightDFGs
4959

5060
export saveDFG, loadDFG
5161

@@ -58,7 +68,7 @@ function __init__()
5868
Rows are all factors, columns are all variables, and each cell contains either nothing or the symbol of the relating factor.
5969
The first column is the factor headings.
6070
"""
61-
function getAdjacencyMatrixDataFrame(dfg::Union{GraphsDFG, LightGraphsDFG})::Main.DataFrames.DataFrame
71+
function getAdjacencyMatrixDataFrame(dfg::Union{GraphsDFG, MetaGraphsDFG, SymbolDFG, LightDFG})::Main.DataFrames.DataFrame
6272
varLabels = sort(map(v->v.label, getVariables(dfg)))
6373
factLabels = sort(map(f->f.label, getFactors(dfg)))
6474
adjDf = DataFrames.DataFrame(:Factor => Union{Missing, Symbol}[])
@@ -75,18 +85,19 @@ function __init__()
7585
end
7686
end
7787

78-
@require Neo4j="d2adbeaf-5838-5367-8a2f-e46d570981db" begin
79-
# Include the Cloudgraphs API
80-
include("CloudGraphsDFG/CloudGraphsDFG.jl")
81-
end
88+
@require Neo4j="d2adbeaf-5838-5367-8a2f-e46d570981db" begin
89+
# Include the Cloudgraphs API
90+
include("CloudGraphsDFG/CloudGraphsDFG.jl")
91+
end
8292

83-
@require GraphPlot = "a2cc645c-3eea-5389-862e-a155d0052231" begin
84-
include("DFGPlots/DFGPlots.jl")
85-
@reexport using .DFGPlots
86-
end
93+
@require GraphPlot = "a2cc645c-3eea-5389-862e-a155d0052231" begin
94+
include("DFGPlots/DFGPlots.jl")
95+
@reexport using .DFGPlots
96+
end
8797

8898
end
8999

100+
90101
# not sure where to put
91102
include("Common.jl")
92103
include("NeedsAHome.jl")

src/GraphsDFG/entities/GraphsDFG.jl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,21 @@ const FGType = Graphs.GenericIncidenceList{GraphsNode,Graphs.Edge{GraphsNode},Di
1111
mutable struct GraphsDFG{T <: AbstractParams} <: AbstractDFG
1212
g::FGType
1313
description::String
14+
userId::String
15+
robotId::String
16+
sessionId::String
1417
nodeCounter::Int64
1518
labelDict::Dict{Symbol, Int64}
1619
addHistory::Vector{Symbol} #TODO: Discuss more - is this an audit trail?
1720
solverParams::T # Solver parameters
18-
GraphsDFG{T}(g::FGType=Graphs.incdict(GraphsNode,is_directed=false),
19-
d::String="Graphs.jl implementation",
20-
n::Int64=0,
21-
l::Dict{Symbol, Int64}=Dict{Symbol, Int64}(),
22-
a::Vector{Symbol}=Symbol[];
23-
params::T=NoSolverParams()) where T <: AbstractParams = new{T}(g, d, n, l, a, params)
2421
end
22+
23+
GraphsDFG{T}( g::FGType=Graphs.incdict(GraphsNode,is_directed=false),
24+
d::String="Graphs.jl implementation",
25+
n::Int64=0,
26+
l::Dict{Symbol, Int64}=Dict{Symbol, Int64}(),
27+
a::Vector{Symbol}=Symbol[];
28+
userId::String = "UserID",
29+
robotId::String = "robotID",
30+
sessionId::String = "sessionID",
31+
params::T=NoSolverParams()) where T <: AbstractParams = GraphsDFG{T}(g, d, userId, robotId, sessionId, n, l, a, params)

src/GraphsDFG/services/GraphsDFG.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,21 @@ function getAdjacencyMatrix(dfg::GraphsDFG)::Matrix{Union{Nothing, Symbol}}
484484
return adjMat
485485
end
486486

487+
function getAdjacencyMatrixSparse(dfg::GraphsDFG)::Tuple{LightGraphs.SparseMatrixCSC, Vector{Symbol}, Vector{Symbol}}
488+
varLabels = map(v->v.label, getVariables(dfg))
489+
factLabels = map(f->f.label, getFactors(dfg))
490+
491+
vDict = Dict(varLabels .=> [1:length(varLabels)...])
492+
493+
adjMat = spzeros(Int, length(factLabels), length(varLabels))
494+
495+
for (fIndex, factLabel) in enumerate(factLabels)
496+
factVars = getNeighbors(dfg, getFactor(dfg, factLabel))
497+
map(vLabel -> adjMat[fIndex,vDict[vLabel]] = 1, factVars)
498+
end
499+
return adjMat, varLabels, factLabels
500+
end
501+
487502
"""
488503
$(SIGNATURES)
489504
Produces a dot-format of the graph for visualization.

src/LightDFG/FactorGraphs/BiMaps.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# import Base: getindex, setindex!, firstindex, lastindex, iterate, keys, isempty
2+
struct BiDictMap{T <: Integer}
3+
int_sym::Dict{T,Symbol}
4+
sym_int::Dict{Symbol,T}
5+
end
6+
7+
BiDictMap{T}(;sizehint=100) where T<:Integer = begin
8+
int_sym = Dict{T,Symbol}()
9+
sizehint!(int_sym, sizehint)
10+
sym_int = Dict{Symbol,T}()
11+
sizehint!(sym_int, sizehint)
12+
BiDictMap{T}(int_sym, sym_int)
13+
end
14+
15+
BiDictMap(;sizehint=100) = BiDictMap{Int}(;sizehint=sizehint)
16+
17+
18+
Base.getindex(b::BiDictMap, key::Int) = b.int_sym[key]
19+
Base.getindex(b::BiDictMap, key::Symbol) = b.sym_int[key]
20+
21+
# setindex!(b, value, key) = b[key] = value
22+
function Base.setindex!(b::BiDictMap, s::Symbol, i::Int)
23+
haskey(b.sym_int, s) && delete!(b.int_sym, b[s])
24+
haskey(b.int_sym, i) && delete!(b.sym_int, b[i])
25+
26+
b.int_sym[i] = s
27+
b.sym_int[s] = i
28+
end
29+
30+
function Base.setindex!(b::BiDictMap, i::Int, s::Symbol)
31+
haskey(b.int_sym, i) && delete!(b.sym_int, b[i])
32+
haskey(b.sym_int, s) && delete!(b.int_sym, b[s])
33+
34+
b.int_sym[i] = s
35+
b.sym_int[s] = i
36+
end
37+
38+
function Base.delete!(b::BiDictMap, i::Int)
39+
s = b[i]
40+
delete!(b.int_sym, i)
41+
delete!(b.sym_int, s)
42+
return b
43+
end
44+
45+
Base.haskey(b::BiDictMap, s::Symbol) = haskey(b.sym_int, s)
46+
Base.haskey(b::BiDictMap, i::Int) = haskey(b.int_sym, i)
47+
48+
Base.length(b::BiDictMap) = length(b.int_sym)
49+
Base.firstindex(v::BiDictMap) = 1
50+
Base.lastindex(v::BiDictMap) = length(v.int_sym)
51+
Base.iterate(v::BiDictMap, i=1) = (length(v.int_sym) < i ? nothing : (v.int_sym[i], i + 1))
52+
Base.keys(v::BiDictMap) = Base.OneTo(length(v.int_sym))
53+
Base.isempty(v::BiDictMap) = (length(v.int_sym) == 0)

0 commit comments

Comments
 (0)