From c66e2b87406fd09453bd0a1186ada2a2a45346ff Mon Sep 17 00:00:00 2001 From: dehann Date: Thu, 12 Sep 2019 21:57:06 -0400 Subject: [PATCH 1/5] some code cleanup, more dispatch possible --- src/CloudGraphsDFG/services/CloudGraphsDFG.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CloudGraphsDFG/services/CloudGraphsDFG.jl b/src/CloudGraphsDFG/services/CloudGraphsDFG.jl index 48662c54..6d6a1e4b 100644 --- a/src/CloudGraphsDFG/services/CloudGraphsDFG.jl +++ b/src/CloudGraphsDFG/services/CloudGraphsDFG.jl @@ -739,11 +739,11 @@ Get a deep subgraph copy from the DFG given a list of variables and factors. Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created. 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. """ -function getSubgraph(dfg::CloudGraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false, addToDFG::Union{Nothing, CloudGraphsDFG}=nothing)::CloudGraphsDFG +function getSubgraph(dfg::CloudGraphsDFG, + variableFactorLabels::Vector{Symbol}, + includeOrphanFactors::Bool=false, + addToDFG::G=_getDuplicatedEmptyDFG(dfg) )::G where {G <: AbstractDFG} # Making a copy session if not specified - if addToDFG == nothing - addToDFG = _getDuplicatedEmptyDFG(dfg) - end _copyIntoGraph!(dfg, addToDFG, variableFactorLabels, includeOrphanFactors) From 186618d6d723a13507d1b3af0d1bfaa2810f1b1a Mon Sep 17 00:00:00 2001 From: gearsad Date: Thu, 19 Sep 2019 23:52:09 -0500 Subject: [PATCH 2/5] WIP on cleanup and interface refactoring --- src/GraphsDFG/services/GraphsDFG.jl | 21 +- src/LightDFG/entities/LightDFG.jl | 3 +- src/services/AbstractDFG.jl | 334 +++++++++++++++++- test/interfaceTests.jl | 12 +- test/{ => obsolete_nowinRoME}/FileDFG.jl | 0 .../HexagonalCloud.jl | 0 .../HexagonalLightGraphs.jl | 0 .../cloudGraphsDFGTests.jl | 0 test/runtests.jl | 39 -- 9 files changed, 340 insertions(+), 69 deletions(-) rename test/{ => obsolete_nowinRoME}/FileDFG.jl (100%) rename test/{ => obsolete_nowinRoME}/HexagonalCloud.jl (100%) rename test/{ => obsolete_nowinRoME}/HexagonalLightGraphs.jl (100%) rename test/{ => obsolete_nowinRoME}/cloudGraphsDFGTests.jl (100%) diff --git a/src/GraphsDFG/services/GraphsDFG.jl b/src/GraphsDFG/services/GraphsDFG.jl index 37e88de6..1380cba2 100644 --- a/src/GraphsDFG/services/GraphsDFG.jl +++ b/src/GraphsDFG/services/GraphsDFG.jl @@ -447,19 +447,14 @@ end """ $(SIGNATURES) -Get a deep subgraph copy from the DFG given a list of variables and factors. -Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created. -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. -""" -function getSubgraph(dfg::GraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false, addToDFG::GraphsDFG=GraphsDFG{AbstractParams}())::GraphsDFG - for label in variableFactorLabels - if !haskey(dfg.labelDict, label) - error("Variable/factor with label '$(label)' does not exist in the factor graph") - end - end - - _copyIntoGraph!(dfg, addToDFG, variableFactorLabels, includeOrphanFactors) - return addToDFG +Gets an empty and unique CloudGraphsDFG derived from an existing DFG. +""" +function _getDuplicatedEmptyDFG(dfg::GraphsDFG)::GraphsDFG + newDfg = GraphsDFG{typeof(dfg.solverParams)}(; + userId=dfg.userId, robotId=dfg.robotId, sessionId=dfg.sessionId, + params=deepcopy(dfg.solverParams)) + newDfg.description ="(Copy of) $(dfg.description)" + return newDfg end """ diff --git a/src/LightDFG/entities/LightDFG.jl b/src/LightDFG/entities/LightDFG.jl index 705532b2..c91824fe 100644 --- a/src/LightDFG/entities/LightDFG.jl +++ b/src/LightDFG/entities/LightDFG.jl @@ -37,7 +37,8 @@ Base.getproperty(x::LightDFG,f::Symbol) = begin @error "Depreciated? returning number of nodes" nv(x.g) elseif f == :labelDict - @error "Depreciated? Concider using exists(dfg,label) instead. Returing internals copy" + @error "Depreciated? Consider using exists(dfg,label) instead. Returning internals copy" + #TODO: https://github.com/JuliaRobotics/DistributedFactorGraphs.jl/issues/111 copy(x.g.labels.sym_int) else getfield(x,f) diff --git a/src/services/AbstractDFG.jl b/src/services/AbstractDFG.jl index c12e1ca0..ad68e3dc 100644 --- a/src/services/AbstractDFG.jl +++ b/src/services/AbstractDFG.jl @@ -25,6 +25,327 @@ function getSerializationModule(dfg::G)::Module where G <: AbstractDFG return Main end +## Utility functions for getting type names and modules (from IncrementalInference) +function _getmodule(t::T) where T + T.name.module +end +function _getname(t::T) where T + T.name.name +end + +## Interface for an AbstractDFG + +""" + $(SIGNATURES) +True if the variable or factor exists in the graph. +""" +function exists(dfg::G, node::N) where {G <: AbstractDFG, N <: DFGNode} + error("exists not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Add a DFGVariable to a DFG. +""" +function addVariable!(dfg::G, variable::DFGVariable)::Bool where G <: AbstractDFG + error("addVariable! not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Add a DFGFactor to a DFG. +""" +function addFactor!(dfg::G, variables::Vector{DFGVariable}, factor::DFGFactor)::Bool where G <: AbstractDFG + error("addFactor! not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Add a DFGFactor to a DFG. +""" +function addFactor!(dfg::G, variableIds::Vector{Symbol}, factor::DFGFactor)::Bool where G <: AbstractDFG + error("addFactor! not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a DFGVariable from a DFG using its underlying integer ID. +""" +function getVariable(dfg::G, variableId::Int64)::DFGVariable where G <: AbstractDFG + error("getVariable not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a DFGVariable from a DFG using its label. +""" +function getVariable(dfg::G, label::Union{Symbol, String})::DFGVariable where G <: AbstractDFG + error("getVariable not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a DFGFactor from a DFG using its underlying integer ID. +""" +function getFactor(dfg::G, factorId::Int64)::DFGFactor where G <: AbstractDFG + error("getFactor not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a DFGFactor from a DFG using its label. +""" +function getFactor(dfg::G, label::Union{Symbol, String})::DFGFactor where G <: AbstractDFG + error("getFactor not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Update a complete DFGVariable in the DFG. +""" +function updateVariable!(dfg::G, variable::DFGVariable)::DFGVariable where G <: AbstractDFG + error("updateVariable! not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Update a complete DFGFactor in the DFG. +""" +function updateFactor!(dfg::G, factor::DFGFactor)::DFGFactor where G <: AbstractDFG + error("updateFactor! not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Delete a DFGVariable from the DFG using its label. +""" +function deleteVariable!(dfg::G, label::Symbol)::DFGVariable where G <: AbstractDFG + error("deleteVariable! not implemented for $(typeof(dfg))") +end + +#Alias +""" + $(SIGNATURES) +Delete a referenced DFGVariable from the DFG. +""" +function deleteVariable!(dfg::G, variable::DFGVariable)::DFGVariable where G <: AbstractDFG + return deleteVariable!(dfg, variable.label) +end + +""" + $(SIGNATURES) +Delete a DFGFactor from the DFG using its label. +""" +function deleteFactor!(dfg::G, label::Symbol)::DFGFactor where G <: AbstractDFG + error("deleteFactors not implemented for $(typeof(dfg))") +end + +# Alias +""" + $(SIGNATURES) +Delete the referened DFGFactor from the DFG. +""" +function deleteFactor!(dfg::G, factor::DFGFactor)::DFGFactor where G <: AbstractDFG + return deleteFactor!(dfg, factor.label) +end + +""" + $(SIGNATURES) +List the DFGVariables in the DFG. +Optionally specify a label regular expression to retrieves a subset of the variables. +""" +function getVariables(dfg::G, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{DFGVariable} where G <: AbstractDFG + error("getVariables not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a list of IDs of the DFGVariables in the DFG. +Optionally specify a label regular expression to retrieves a subset of the variables. + +Example +```julia +getVariableIds(dfg, r"l", tags=[:APRILTAG;]) +``` + +Related + +ls +""" +function getVariableIds(dfg::G, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol} where G <: AbstractDFG + vars = getVariables(dfg, regexFilter, tags=tags) + # mask = map(v -> length(intersect(v.tags, tags)) > 0, vars ) + return map(v -> v.label, vars) +end + +# Alias +""" + $(SIGNATURES) +List the DFGVariables in the DFG. +Optionally specify a label regular expression to retrieves a subset of the variables. +""" +function ls(dfg::G, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol} where G <: AbstractDFG + return getVariableIds(dfg, regexFilter, tags=tags) +end + +""" + $(SIGNATURES) +List the DFGFactors in the DFG. +Optionally specify a label regular expression to retrieves a subset of the factors. +""" +function getFactors(dfg::G, regexFilter::Union{Nothing, Regex}=nothing)::Vector{DFGFactor} where G <: AbstractDFG + error("getFactors not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a list of the IDs of the DFGFactors in the DFG. +Optionally specify a label regular expression to retrieves a subset of the factors. +""" +function getFactorIds(dfg::G, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} where G <: AbstractDFG + return map(f -> f.label, getFactors(dfg, regexFilter)) +end + +""" + $(SIGNATURES) +List the DFGFactors in the DFG. +Optionally specify a label regular expression to retrieves a subset of the factors. +""" +# Alias +function lsf(dfg::G, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} where G <: AbstractDFG + return getFactorIds(dfg, regexFilter) +end + +""" + $(SIGNATURES) +Alias for getNeighbors - returns neighbors around a given node label. +""" +function lsf(dfg::G, label::Symbol)::Vector{Symbol} where G <: AbstractDFG + return getNeighbors(dfg, label) +end + +""" + $(SIGNATURES) +Checks if the graph is fully connected, returns true if so. +""" +function isFullyConnected(dfg::G)::Bool where G <: AbstractDFG + error("isFullyConnected not implemented for $(typeof(dfg))") +end + +#Alias +""" + $(SIGNATURES) +Checks if the graph is not fully connected, returns true if it is not contiguous. +""" +function hasOrphans(dfg::G)::Bool where G <: AbstractDFG + return !isFullyConnected(dfg) +end + +""" + $(SIGNATURES) +Retrieve a list of labels of the immediate neighbors around a given variable or factor. +""" +function getNeighbors(dfg::G, node::T; ready::Union{Nothing, Int}=nothing, backendset::Union{Nothing, Int}=nothing)::Vector{Symbol} where {G <: AbstractDFG, T <: DFGNode} + error("getNeighbors not implemented for $(typeof(dfg))") +end +""" + $(SIGNATURES) +Retrieve a list of labels of the immediate neighbors around a given variable or factor specified by its label. +""" +function getNeighbors(dfg::G, label::Symbol; ready::Union{Nothing, Int}=nothing, backendset::Union{Nothing, Int}=nothing)::Vector{Symbol} where G <: AbstractDFG + error("getNeighbors not implemented for $(typeof(dfg))") +end + +# Aliases +""" + $(SIGNATURES) +Retrieve a list of labels of the immediate neighbors around a given variable or factor. +""" +function ls(dfg::G, node::T)::Vector{Symbol} where {G <: AbstractDFG, T <: DFGNode} + return getNeighbors(dfg, node) +end +""" + $(SIGNATURES) +Retrieve a list of labels of the immediate neighbors around a given variable or factor specified by its label. +""" +function ls(dfg::G, label::Symbol)::Vector{Symbol} where G <: AbstractDFG + return getNeighbors(dfg, label) +end + +""" + $(SIGNATURES) +Gets an empty and unique CloudGraphsDFG derived from an existing DFG. +""" +function _getDuplicatedEmptyDFG(dfg::G)::G where G <: AbstractDFG + error("_getDuplicatedEmptyDFG not implemented for $(typeof(dfg))") +end + +# TODO: NEED TO FIGURE OUT SIGNATURE FOR DEFAULT ARGS + +""" + $(SIGNATURES) +Retrieve a deep subgraph copy around a given variable or factor. +Optionally provide a distance to specify the number of edges should be followed. +Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created. +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. +""" +function getSubgraphAroundNode(dfg::G, node::T, distance::Int64=1, includeOrphanFactors::Bool=false, addToDFG::H=_getDuplicatedEmptyDFG(dfg))::G where {G <: AbstractDFG, H <: AbstractDFG, P <: AbstractParams, T <: DFGNode} + error("getSubgraphAroundNode not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Get a deep subgraph copy from the DFG given a list of variables and factors. +Optionally provide an existing subgraph addToDFG, the extracted nodes will be copied into this graph. By default a new subgraph will be created. +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. +""" +function getSubgraph(dfg::G, + variableFactorLabels::Vector{Symbol}, + includeOrphanFactors::Bool=false, + addToDFG::H=_getDuplicatedEmptyDFG(dfg))::H where {G <: AbstractDFG, H <: AbstractDFG} + for label in variableFactorLabels + if !exists(dfg, label) + error("Variable/factor with label '$(label)' does not exist in the factor graph") + end + end + + _copyIntoGraph!(dfg, addToDFG, variableFactorLabels, includeOrphanFactors) + return addToDFG +end + +""" + $(SIGNATURES) +Get an adjacency matrix for the DFG, returned as a Matrix{Union{Nothing, Symbol}}. +Rows are all factors, columns are all variables, and each cell contains either nothing or the symbol of the relating factor. +The first row and first column are factor and variable headings respectively. +""" +function getAdjacencyMatrix(dfg::G)::Matrix{Union{Nothing, Symbol}} where G <: AbstractDFG + error("getAdjacencyMatrix not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Produces a dot-format of the graph for visualization. +""" +function toDot(dfg::G)::String where G <: AbstractDFG + error("toDot not implemented for $(typeof(dfg))") +end + +""" + $(SIGNATURES) +Produces a dot file of the graph for visualization. +Download XDot to see the data + +Note +- Default location "/tmp/dfg.dot" -- MIGHT BE REMOVED +- Can be viewed with the `xdot` system application. +- Based on graphviz.org +""" +function toDotFile(dfg::G, fileName::String="/tmp/dfg.dot")::Nothing where G <: AbstractDFG + error("toDotFile not implemented for $(typeof(dfg))") +end + + """ $(SIGNATURES) Common function for copying nodes from one graph into another graph. @@ -67,18 +388,11 @@ function _copyIntoGraph!(sourceDFG::G, destDFG::H, variableFactorLabels::Vector{ return nothing end -## Utility functions for getting type names and modules (from IncrementalInference) -function _getmodule(t::T) where T - T.name.module -end -function _getname(t::T) where T - T.name.name -end - -## Interfaces """ $(SIGNATURES) Get an adjacency matrix for the DFG, returned as a tuple: adjmat::SparseMatrixCSC{Int}, var_labels::Vector{Symbol) fac_labels::Vector{Symbol). Rows are the factors, columns are the variables, with the corresponding labels in fac_labels,var_labels. """ -getAdjacencyMatrixSparse(dfg::AbstractDFG) = error("getAdjacencyMatrixSparse not implemented for $(typeof(dfg))") +function getAdjacencyMatrixSparse(dfg::G) where G <: AbstractDFG + error("getAdjacencyMatrixSparse not implemented for $(typeof(dfg))") +end diff --git a/test/interfaceTests.jl b/test/interfaceTests.jl index 67bd089e..6a1abd82 100644 --- a/test/interfaceTests.jl +++ b/test/interfaceTests.jl @@ -115,16 +115,17 @@ end #sparse adjMat, v_ll, f_ll = getAdjacencyMatrixSparse(dfg) @test size(adjMat) == (1,3) - #TODO hoe om te toets, volgorde nie altyd dieselfde nie - # @test adjMat[1, 1] == 0 - # @test adjMat[1, 2] == 1 - # @test adjMat[1, 3] == 1 + + # Checking the elements of adjacency, its not sorted so need indexing function + indexOf = (arr, el1) -> findfirst(el2->el2==el1, arr) + @test adjMat[1, indexOf(v_ll, :orphan)] == 0 + @test adjMat[1, indexOf(v_ll, :a)] == 1 + @test adjMat[1, indexOf(v_ll, :b)] == 1 @test symdiff(v_ll, [:a, :b, :orphan]) == Symbol[] @test symdiff(f_ll, [:f1, :f1, :f1]) == Symbol[] end # Deletions -# Not supported at present @testset "Deletions" begin deleteFactor!(dfg, :f1) @test getFactorIds(dfg) == [] @@ -142,7 +143,6 @@ verts[7].ready = 1 verts[8].backendset = 1 map(v -> addVariable!(dfg, v), verts) map(n -> addFactor!(dfg, [verts[n], verts[n+1]], DFGFactor{Int, :Symbol}(Symbol("x$(n)x$(n+1)f1"))), 1:(numNodes-1)) -# map(n -> addFactor!(dfg, [verts[n], verts[n+2]], DFGFactor(Symbol("x$(n)x$(n+2)f2"))), 1:2:(numNodes-2)) @testset "Getting Neighbors" begin global dfg,verts diff --git a/test/FileDFG.jl b/test/obsolete_nowinRoME/FileDFG.jl similarity index 100% rename from test/FileDFG.jl rename to test/obsolete_nowinRoME/FileDFG.jl diff --git a/test/HexagonalCloud.jl b/test/obsolete_nowinRoME/HexagonalCloud.jl similarity index 100% rename from test/HexagonalCloud.jl rename to test/obsolete_nowinRoME/HexagonalCloud.jl diff --git a/test/HexagonalLightGraphs.jl b/test/obsolete_nowinRoME/HexagonalLightGraphs.jl similarity index 100% rename from test/HexagonalLightGraphs.jl rename to test/obsolete_nowinRoME/HexagonalLightGraphs.jl diff --git a/test/cloudGraphsDFGTests.jl b/test/obsolete_nowinRoME/cloudGraphsDFGTests.jl similarity index 100% rename from test/cloudGraphsDFGTests.jl rename to test/obsolete_nowinRoME/cloudGraphsDFGTests.jl diff --git a/test/runtests.jl b/test/runtests.jl index a9af1ed8..68f740e5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,42 +9,3 @@ for api in apis include("interfaceTests.jl") end end - -# Test extensions -# @testset "DFG Extensions" begin -# include("FileDFG.jl") -# end - -# if !(get(ENV, "TRAVIS", "") == "true") -# @testset "Local Testsets" begin -# @testset "HexagonalLightGraphs" begin -# include("HexagonalLightGraphs.jl") -# end -# end -# end - -# Test other interfaces that are not yet compatible for the general tests. -# @testset "CloudGraphsDFG Drive: " begin -# include("cloudGraphsDFGTests.jl") -# end - -# function decodePackedType(packeddata::GenericFunctionNodeData{Symbol,<:AbstractString}, notused::String) -# usrtyp = convert(FunctorInferenceType, packeddata.fnc) -# fulltype = FunctionNodeData{Symbol} -# return convert(fulltype, packeddata) -# end -# -# cgDFG = CloudGraphsDFG("localhost", 7474, "neo4j", "test", -# "testUser", "testRobot", "testSession", -# nothing, -# nothing, -# decodePackedType) -# if haskey(ENV, "TRAVIS") -# cgDFG = CloudGraphsDFG("localhost", 7474, "neo4j", "neo4j", -# "testUser", "testRobot", "testSession", -# nothing, -# nothing, -# decodePackedType) -# end -# # Completely wipe out the graph before testing. -# clearRobot!!(cgDFG) From 9229e13526dd9b91d675f49a27248d98e654a0f2 Mon Sep 17 00:00:00 2001 From: gearsad Date: Sun, 22 Sep 2019 08:28:56 -0500 Subject: [PATCH 3/5] Refactoring and cleanup of DFG interface --- src/CloudGraphsDFG/services/CloudGraphsDFG.jl | 4 +-- src/Common.jl | 9 +++++- src/GraphsDFG/services/GraphsDFG.jl | 28 +++++++++---------- src/services/AbstractDFG.jl | 28 ++++++++++++++----- test/interfaceTests.jl | 3 ++ 5 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/CloudGraphsDFG/services/CloudGraphsDFG.jl b/src/CloudGraphsDFG/services/CloudGraphsDFG.jl index 6d6a1e4b..04064c40 100644 --- a/src/CloudGraphsDFG/services/CloudGraphsDFG.jl +++ b/src/CloudGraphsDFG/services/CloudGraphsDFG.jl @@ -63,8 +63,8 @@ getDescription(dfg::CloudGraphsDFG) = dfg.description setDescription(dfg::CloudGraphsDFG, description::String) = dfg.description = description getAddHistory(dfg::CloudGraphsDFG) = dfg.addHistory getSolverParams(dfg::CloudGraphsDFG) = dfg.solverParams -function setSolverParams(dfg::CloudGraphsDFG, solverParams::T) where T <: AbstractParams - dfg.solverParams = solverParams +function setSolverParams(dfg::CloudGraphsDFG, solverParams::T)::T where T <: AbstractParams + return dfg.solverParams = solverParams end """ diff --git a/src/Common.jl b/src/Common.jl index 09541721..20bb6995 100644 --- a/src/Common.jl +++ b/src/Common.jl @@ -1,4 +1,3 @@ - export sortVarNested export isPrior, lsfPriors export getData @@ -7,6 +6,14 @@ export getFactorType, getfnctype export lsTypes, lsfTypes export lsWho, lsfWho +## Utility functions for getting type names and modules (from IncrementalInference) +function _getmodule(t::T) where T + T.name.module +end +function _getname(t::T) where T + T.name.name +end + """ $(SIGNATURES) Test if all elements of the string is a number: Ex, "123" is true, "1_2" is false. diff --git a/src/GraphsDFG/services/GraphsDFG.jl b/src/GraphsDFG/services/GraphsDFG.jl index 1380cba2..8be18e81 100644 --- a/src/GraphsDFG/services/GraphsDFG.jl +++ b/src/GraphsDFG/services/GraphsDFG.jl @@ -22,10 +22,20 @@ setDescription(dfg::GraphsDFG, description::String) = dfg.description = descript getInnerGraph(dfg::GraphsDFG) = dfg.g getAddHistory(dfg::GraphsDFG) = dfg.addHistory getSolverParams(dfg::GraphsDFG) = dfg.solverParams +function setSolverParams(dfg::GraphsDFG, solverParams::T) where T <: AbstractParams + dfg.solverParams = solverParams +end -# setSolverParams(dfg::GraphsDFG, solverParams) = dfg.solverParams = solverParams -function setSolverParams(dfg::GraphsDFG, solverParams::P) where P <: AbstractParams - dfg.solverParams = solverParams +""" + $(SIGNATURES) +Gets an empty and unique CloudGraphsDFG derived from an existing DFG. +""" +function _getDuplicatedEmptyDFG(dfg::GraphsDFG)::GraphsDFG + newDfg = GraphsDFG{typeof(dfg.solverParams)}(; + userId=dfg.userId, robotId=dfg.robotId, sessionId=dfg.sessionId, + params=deepcopy(dfg.solverParams)) + newDfg.description ="(Copy of) $(dfg.description)" + return newDfg end """ @@ -445,18 +455,6 @@ function getSubgraphAroundNode(dfg::GraphsDFG{P}, node::T, distance::Int64=1, in return addToDFG end -""" - $(SIGNATURES) -Gets an empty and unique CloudGraphsDFG derived from an existing DFG. -""" -function _getDuplicatedEmptyDFG(dfg::GraphsDFG)::GraphsDFG - newDfg = GraphsDFG{typeof(dfg.solverParams)}(; - userId=dfg.userId, robotId=dfg.robotId, sessionId=dfg.sessionId, - params=deepcopy(dfg.solverParams)) - newDfg.description ="(Copy of) $(dfg.description)" - return newDfg -end - """ $(SIGNATURES) Get an adjacency matrix for the DFG, returned as a Matrix{Union{Nothing, Symbol}}. diff --git a/src/services/AbstractDFG.jl b/src/services/AbstractDFG.jl index ad68e3dc..a94567a8 100644 --- a/src/services/AbstractDFG.jl +++ b/src/services/AbstractDFG.jl @@ -1,3 +1,4 @@ +## ===== Interface for an AbstractDFG ===== """ $(SIGNATURES) @@ -25,15 +26,28 @@ function getSerializationModule(dfg::G)::Module where G <: AbstractDFG return Main end -## Utility functions for getting type names and modules (from IncrementalInference) -function _getmodule(t::T) where T - T.name.module +# Accessors +function getLabelDict(dfg::G) where G <: AbstractDFG + error("getLabelDict not implemented for $(typeof(dfg))") end -function _getname(t::T) where T - T.name.name +function getDescription(dfg::G) where G <: AbstractDFG + error("getDescription not implemented for $(typeof(dfg))") +end +function setDescription(dfg::G, description::String) where G <: AbstractDFG + error("setDescription not implemented for $(typeof(dfg))") +end +function getInnerGraph(dfg::G) where G <: AbstractDFG + error("getInnerGraph not implemented for $(typeof(dfg))") +end +function getAddHistory(dfg::G) where G <: AbstractDFG + error("getAddHistory not implemented for $(typeof(dfg))") +end +function getSolverParams(dfg::G) where G <: AbstractDFG + error("getSolverParams not implemented for $(typeof(dfg))") +end +function setSolverParams(dfg::G, solverParams::T) where {G <: AbstractDFG, T <: AbstractParams} + error("setSolverParams not implemented for $(typeof(dfg))") end - -## Interface for an AbstractDFG """ $(SIGNATURES) diff --git a/test/interfaceTests.jl b/test/interfaceTests.jl index 6a1abd82..c1d8e06f 100644 --- a/test/interfaceTests.jl +++ b/test/interfaceTests.jl @@ -92,6 +92,9 @@ end @test label(f1) == f1.label @test data(f1) == f1.data @test id(f1) == f1._internalId + + @test getSolverParams(dfg) != nothing + @test setSolverParams(dfg, getSolverParams(dfg)) == getSolverParams(dfg) end # Connectivity test From f3e8e47d9e9a73b3d6b313d0c1bf88b97bb67908 Mon Sep 17 00:00:00 2001 From: gearsad Date: Sun, 22 Sep 2019 08:43:12 -0500 Subject: [PATCH 4/5] Cleaning up Graphs.jl --- src/GraphsDFG/services/GraphsDFG.jl | 157 ++++++---------------------- 1 file changed, 34 insertions(+), 123 deletions(-) diff --git a/src/GraphsDFG/services/GraphsDFG.jl b/src/GraphsDFG/services/GraphsDFG.jl index 8be18e81..5cec9db3 100644 --- a/src/GraphsDFG/services/GraphsDFG.jl +++ b/src/GraphsDFG/services/GraphsDFG.jl @@ -200,13 +200,6 @@ function deleteVariable!(dfg::GraphsDFG, label::Symbol)::DFGVariable return variable end -#Alias -""" - $(SIGNATURES) -Delete a referenced DFGVariable from the DFG. -""" -deleteVariable!(dfg::GraphsDFG, variable::DFGVariable)::DFGVariable = deleteVariable!(dfg, variable.label) - """ $(SIGNATURES) Delete a DFGFactor from the DFG using its label. @@ -221,13 +214,6 @@ function deleteFactor!(dfg::GraphsDFG, label::Symbol)::DFGFactor return factor end -# Alias -""" - $(SIGNATURES) -Delete the referened DFGFactor from the DFG. -""" -deleteFactor!(dfg::GraphsDFG, factor::DFGFactor)::DFGFactor = deleteFactor!(dfg, factor.label) - """ $(SIGNATURES) List the DFGVariables in the DFG. @@ -245,34 +231,6 @@ function getVariables(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing return variables end -""" - $(SIGNATURES) -Get a list of IDs of the DFGVariables in the DFG. -Optionally specify a label regular expression to retrieves a subset of the variables. - -Example -```julia -getVariableIds(dfg, r"l", tags=[:APRILTAG;]) -``` - -Related - -ls -""" -function getVariableIds(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol} - vars = getVariables(dfg, regexFilter, tags=tags) - # mask = map(v -> length(intersect(v.tags, tags)) > 0, vars ) - map(v -> v.label, vars) -end - -# Alias -""" - $(SIGNATURES) -List the DFGVariables in the DFG. -Optionally specify a label regular expression to retrieves a subset of the variables. -""" -ls(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol} = getVariableIds(dfg, regexFilter, tags=tags) - """ $(SIGNATURES) List the DFGFactors in the DFG. @@ -286,29 +244,6 @@ function getFactors(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing): return factors end -""" - $(SIGNATURES) -Get a list of the IDs of the DFGFactors in the DFG. -Optionally specify a label regular expression to retrieves a subset of the factors. -""" -getFactorIds(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} = map(f -> f.label, getFactors(dfg, regexFilter)) - -""" - $(SIGNATURES) -List the DFGFactors in the DFG. -Optionally specify a label regular expression to retrieves a subset of the factors. -""" -# Alias -lsf(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} = getFactorIds(dfg, regexFilter) - -""" - $(SIGNATURES) -Alias for getNeighbors - returns neighbors around a given node label. -""" -function lsf(dfg::GraphsDFG, label::Symbol)::Vector{Symbol} - return getNeighbors(dfg, label) -end - """ $(SIGNATURES) Checks if the graph is fully connected, returns true if so. @@ -317,14 +252,6 @@ function isFullyConnected(dfg::GraphsDFG)::Bool return length(Graphs.connected_components(dfg.g)) == 1 end -#Alias -""" - $(SIGNATURES) -Checks if the graph is not fully connected, returns true if it is not contiguous. -""" -hasOrphans(dfg::GraphsDFG)::Bool = !isFullyConnected(dfg) - - """ $(SIGNATURES) Retrieve a list of labels of the immediate neighbors around a given variable or factor. @@ -369,56 +296,40 @@ function getNeighbors(dfg::GraphsDFG, label::Symbol; ready::Union{Nothing, Int}= return map(n -> n.dfgNode.label, neighbors) end -# Aliases -""" - $(SIGNATURES) -Retrieve a list of labels of the immediate neighbors around a given variable or factor. -""" -function ls(dfg::GraphsDFG, node::T)::Vector{Symbol} where T <: DFGNode - return getNeighbors(dfg, node) -end -""" - $(SIGNATURES) -Retrieve a list of labels of the immediate neighbors around a given variable or factor specified by its label. -""" -function ls(dfg::GraphsDFG, label::Symbol)::Vector{Symbol} where T <: DFGNode - return getNeighbors(dfg, label) -end - -function _copyIntoGraph!(sourceDFG::GraphsDFG, destDFG::GraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false)::Nothing - # Split into variables and factors - verts = map(id -> sourceDFG.g.vertices[sourceDFG.labelDict[id]], variableFactorLabels) - sourceVariables = filter(n -> n.dfgNode isa DFGVariable, verts) - sourceFactors = filter(n -> n.dfgNode isa DFGFactor, verts) - - # Now we have to add all variables first, - for variable in sourceVariables - if !haskey(destDFG.labelDict, variable.dfgNode.label) - addVariable!(destDFG, deepcopy(variable.dfgNode)) - end - end - # And then all factors to the destDFG. - for factor in sourceFactors - if !haskey(destDFG.labelDict, factor.dfgNode.label) - # Get the original factor variables (we need them to create it) - neighVarIds = getNeighbors(sourceDFG, factor.dfgNode.label) #OLD: in_neighbors(factor, sourceDFG.g) - # Find the labels and associated neighVarIds in our new subgraph - factVariables = DFGVariable[] - for neighVarId in neighVarIds - if haskey(destDFG.labelDict, neighVarId) - push!(factVariables, getVariable(destDFG, neighVarId)) - #otherwise ignore - end - end - - # Only if we have all of them should we add it (otherwise strange things may happen on evaluation) - if includeOrphanFactors || length(factVariables) == length(neighVarIds) - addFactor!(destDFG, factVariables, deepcopy(factor.dfgNode)) - end - end - end - return nothing -end +# function _copyIntoGraph!(sourceDFG::GraphsDFG, destDFG::GraphsDFG, variableFactorLabels::Vector{Symbol}, includeOrphanFactors::Bool=false)::Nothing +# # Split into variables and factors +# verts = map(id -> sourceDFG.g.vertices[sourceDFG.labelDict[id]], variableFactorLabels) +# sourceVariables = filter(n -> n.dfgNode isa DFGVariable, verts) +# sourceFactors = filter(n -> n.dfgNode isa DFGFactor, verts) +# +# # Now we have to add all variables first, +# for variable in sourceVariables +# if !haskey(destDFG.labelDict, variable.dfgNode.label) +# addVariable!(destDFG, deepcopy(variable.dfgNode)) +# end +# end +# # And then all factors to the destDFG. +# for factor in sourceFactors +# if !haskey(destDFG.labelDict, factor.dfgNode.label) +# # Get the original factor variables (we need them to create it) +# neighVarIds = getNeighbors(sourceDFG, factor.dfgNode.label) #OLD: in_neighbors(factor, sourceDFG.g) +# # Find the labels and associated neighVarIds in our new subgraph +# factVariables = DFGVariable[] +# for neighVarId in neighVarIds +# if haskey(destDFG.labelDict, neighVarId) +# push!(factVariables, getVariable(destDFG, neighVarId)) +# #otherwise ignore +# end +# end +# +# # Only if we have all of them should we add it (otherwise strange things may happen on evaluation) +# if includeOrphanFactors || length(factVariables) == length(neighVarIds) +# addFactor!(destDFG, factVariables, deepcopy(factor.dfgNode)) +# end +# end +# end +# return nothing +# end """ $(SIGNATURES) From 77bbed48f70ec1042d118096b897ef439ff270b2 Mon Sep 17 00:00:00 2001 From: dehann Date: Sun, 22 Sep 2019 10:57:25 -0400 Subject: [PATCH 5/5] more ls for types --- src/Common.jl | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Common.jl b/src/Common.jl index 09541721..ce29788b 100644 --- a/src/Common.jl +++ b/src/Common.jl @@ -232,10 +232,38 @@ function lsTypes(dfg::G)::Dict{Symbol, Vector{String}} where G <: AbstractDFG end +function ls(dfg::G, ::Type{T}; solveKey::Symbol=:default) where {G <: AbstractDFG, T <: InferenceVariable} + xx = getVariables(dfg) + mask = getVariableType.(xx, solveKey=solveKey) .|> typeof .== T + vxx = view(xx, mask) + map(x->x.label, vxx) +end + + +function ls(dfg::G, ::Type{T}) where {G <: AbstractDFG, T <: FunctorInferenceType} + xx = getFactors(dfg) + names = getfield.(typeof.(getFactorType.(xx)), :name) .|> Symbol + vxx = view(xx, names .== Symbol(T)) + map(x->x.label, vxx) +end + +function lsf(dfg::G, ::Type{T}) where {G <: AbstractDFG, T <: FunctorInferenceType} + ls(dfg, T) +end + + """ $(SIGNATURES) Gives back all factor labels that fit the bill: lsWho(dfg, :Pose3) + +Dev Notes +- Cloud versions will benefit from less data transfer + - `ls(dfg::C, ::T) where {C <: CloudDFG, T <: ..}` + +Related + +ls, lsf, lsfPriors """ function lsWho(dfg::AbstractDFG, type::Symbol; solveKey::Symbol=:default)::Vector{Symbol} vars = getVariables(dfg) @@ -252,6 +280,14 @@ end $(SIGNATURES) Gives back all factor labels that fit the bill: lsfWho(dfg, :Point2Point2) + +Dev Notes +- Cloud versions will benefit from less data transfer + - `ls(dfg::C, ::T) where {C <: CloudDFG, T <: ..}` + +Related + +ls, lsf, lsfPriors """ function lsfWho(dfg::AbstractDFG, type::Symbol)::Vector{Symbol} facs = getFactors(dfg)